From 8d638fe1b63aa39809be565d94585ccb2389078f Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Mon, 1 Dec 2025 12:09:23 +0300 Subject: [PATCH 01/21] [Logger] feat: add ability to ignore Nest.js contexts (#3701) --- .changeset/slick-dryers-cheat.md | 5 +++++ packages/libs/logger/README.md | 6 ++++++ packages/libs/logger/src/nest-logger.ts | 11 +++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 .changeset/slick-dryers-cheat.md diff --git a/.changeset/slick-dryers-cheat.md b/.changeset/slick-dryers-cheat.md new file mode 100644 index 0000000000..36e0fd6387 --- /dev/null +++ b/.changeset/slick-dryers-cheat.md @@ -0,0 +1,5 @@ +--- +"@human-protocol/logger": minor +--- + +Added ability to ignore logging from Nest.js contexts diff --git a/packages/libs/logger/README.md b/packages/libs/logger/README.md index 45dc2b0824..b093df31ea 100644 --- a/packages/libs/logger/README.md +++ b/packages/libs/logger/README.md @@ -85,6 +85,12 @@ import { NestLogger } from '@human-protocol/logger'; // initialize an overridden instance export const nestLoggerOverride = new NestLogger( defaultAppLogger.child({ name: 'NestLogger' }), + /** + * You may also want to disable logging from some noisy Nest.js contexts, + * e.g. app initialization logging. + * NOTE: it will disable logging on all levels for these contexts + */ + ['InstanceLoader', 'RouterExplorer', 'RoutesResolver'], ); diff --git a/packages/libs/logger/src/nest-logger.ts b/packages/libs/logger/src/nest-logger.ts index ca29a041a3..84762c0757 100644 --- a/packages/libs/logger/src/nest-logger.ts +++ b/packages/libs/logger/src/nest-logger.ts @@ -4,7 +4,10 @@ import type { LoggerService } from '@nestjs/common'; import { Logger, LogLevel, LogMeta } from './types'; class NestLogger implements LoggerService { - constructor(private readonly loggerInstance: Logger) {} + constructor( + private readonly loggerInstance: Logger, + readonly contextsToIgnore: string[] = [], + ) {} log(message: any, ...optionalParams: any[]) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument @@ -60,7 +63,7 @@ class NestLogger implements LoggerService { message: unknown, ...optionalParams: unknown[] ): void { - const logMeta: LogMeta = {}; + const logMeta: LogMeta & { context?: string } = {}; let params: unknown[] = []; // Nest always add "context" as last param @@ -74,6 +77,10 @@ class NestLogger implements LoggerService { } } + if (logMeta.context && this.contextsToIgnore.includes(logMeta.context)) { + return; + } + // Case when Nest logs something other than context if (params.length) { logMeta.messages = params; From dddf2b8cb940efef65d039520eabb8c8dcb7fae6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:07:15 +0100 Subject: [PATCH 02/21] chore(deps): bump minio from 7.1.3 to 8.0.6 (#3559) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Francisco López --- .changeset/gold-doodles-ask.md | 6 + .../exchange-oracle/server/package.json | 2 +- .../server/scripts/setup-kv-store.ts | 2 +- .../src/common/guards/strategy/jwt.http.ts | 7 +- .../server/src/common/utils/storage.ts | 33 ++ .../src/modules/job/job.service.spec.ts | 28 +- .../server/src/modules/job/job.service.ts | 5 +- .../modules/storage/storage.service.spec.ts | 26 +- .../src/modules/storage/storage.service.ts | 5 +- .../fortune/recording-oracle/package.json | 2 +- .../scripts/setup-kv-store.ts | 2 +- .../src/common/utils/storage.ts | 33 ++ .../src/modules/job/job.service.spec.ts | 49 +-- .../modules/storage/storage.service.spec.ts | 24 +- .../src/modules/storage/storage.service.ts | 5 +- .../server/src/common/utils/storage.ts | 33 ++ .../integrations/kv-store/kv-store.gateway.ts | 10 +- .../apps/job-launcher/server/package.json | 2 +- .../server/scripts/setup-kv-store.ts | 2 +- .../server/src/modules/job/job.service.ts | 2 - .../src/modules/manifest/manifest.service.ts | 8 +- .../src/modules/storage/storage.service.ts | 1 + .../reputation-oracle/server/package.json | 2 +- .../server/scripts/setup-kv-store.ts | 2 +- .../src/modules/storage/storage.service.ts | 1 + .../sdk/python/human-protocol-sdk/Pipfile | 1 - .../human_protocol_sdk/storage/__init__.py | 11 - .../storage/storage_client.py | 379 ----------------- .../storage/storage_utils.py | 58 --- .../human_protocol_sdk/storage/__init__.py | 0 .../storage/test_storage_client.py | 311 -------------- .../storage/test_storage_utils.py | 37 -- .../human-protocol-sdk/package.json | 1 - .../human-protocol-sdk/src/error.ts | 36 -- .../human-protocol-sdk/src/index.ts | 2 - .../human-protocol-sdk/src/storage.ts | 313 -------------- .../human-protocol-sdk/src/types.ts | 57 --- .../human-protocol-sdk/test/storage.test.ts | 400 ------------------ yarn.lock | 42 +- 39 files changed, 219 insertions(+), 1721 deletions(-) create mode 100644 .changeset/gold-doodles-ask.md create mode 100644 packages/apps/fortune/exchange-oracle/server/src/common/utils/storage.ts create mode 100644 packages/apps/fortune/recording-oracle/src/common/utils/storage.ts create mode 100644 packages/apps/human-app/server/src/common/utils/storage.ts delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/__init__.py delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_client.py delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_utils.py delete mode 100644 packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/__init__.py delete mode 100644 packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_client.py delete mode 100644 packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_utils.py delete mode 100644 packages/sdk/typescript/human-protocol-sdk/src/storage.ts delete mode 100644 packages/sdk/typescript/human-protocol-sdk/test/storage.test.ts diff --git a/.changeset/gold-doodles-ask.md b/.changeset/gold-doodles-ask.md new file mode 100644 index 0000000000..6c88f4957e --- /dev/null +++ b/.changeset/gold-doodles-ask.md @@ -0,0 +1,6 @@ +--- +"@human-protocol/sdk": major +"@human-protocol/python-sdk": major +--- + +Remove deprecated storage utilities and tests diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index cb840b8a31..74e23e701c 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -50,7 +50,7 @@ "ethers": "~6.15.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", - "minio": "7.1.3", + "minio": "8.0.6", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "pg": "8.13.1", diff --git a/packages/apps/fortune/exchange-oracle/server/scripts/setup-kv-store.ts b/packages/apps/fortune/exchange-oracle/server/scripts/setup-kv-store.ts index d28014975b..21c9c9a9bf 100644 --- a/packages/apps/fortune/exchange-oracle/server/scripts/setup-kv-store.ts +++ b/packages/apps/fortune/exchange-oracle/server/scripts/setup-kv-store.ts @@ -73,7 +73,7 @@ async function setupPublicKeyFile( throw new Error('Bucket does not exists'); } - await minioClient.putObject(s3Bucket, keyName, publicKey, { + await minioClient.putObject(s3Bucket, keyName, publicKey, undefined, { 'Content-Type': 'text/plain', 'Cache-Control': 'no-store', }); diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts b/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts index 7f948fddc8..7c99af6b7a 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/common/guards/strategy/jwt.http.ts @@ -3,7 +3,7 @@ import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { KVStore__factory } from '@human-protocol/core/typechain-types'; -import { ChainId, NETWORKS, StorageClient } from '@human-protocol/sdk'; +import { ChainId, NETWORKS } from '@human-protocol/sdk'; import { ethers } from 'ethers'; import * as jwt from 'jsonwebtoken'; import { JWT_KVSTORE_KEY, KYC_APPROVED } from '../../../common/constant'; @@ -11,6 +11,7 @@ import { Role } from '../../../common/enums/role'; import { JwtUser } from '../../../common/types/jwt'; import { Web3Service } from '../../../modules/web3/web3.service'; import { AuthError, ValidationError } from '../../errors'; +import { downloadFileFromUrl } from '../../utils/storage'; @Injectable() export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { @@ -47,9 +48,7 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { address, JWT_KVSTORE_KEY, ); - publicKey = (await StorageClient.downloadFileFromUrl( - url, - )) as string; + publicKey = (await downloadFileFromUrl(url)) as string; this.publicKeyCache.set(cacheKey, { value: publicKey, diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/utils/storage.ts b/packages/apps/fortune/exchange-oracle/server/src/common/utils/storage.ts new file mode 100644 index 0000000000..104070d7af --- /dev/null +++ b/packages/apps/fortune/exchange-oracle/server/src/common/utils/storage.ts @@ -0,0 +1,33 @@ +import axios from 'axios'; +import { HttpStatus } from '@nestjs/common'; + +export const isValidUrl = (maybeUrl: string): boolean => { + try { + const { protocol } = new URL(maybeUrl); + return protocol === 'http:' || protocol === 'https:'; + } catch { + return false; + } +}; + +export async function downloadFileFromUrl(url: string): Promise { + if (!isValidUrl(url)) { + throw new Error('Invalid URL string'); + } + + try { + const { data, status } = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (status !== HttpStatus.OK) { + throw new Error('Storage file not found'); + } + + return data; + } catch { + throw new Error('Storage file not found'); + } +} diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts index 62d50a8903..d39c5d9dd6 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.spec.ts @@ -1,11 +1,6 @@ import { createMock } from '@golevelup/ts-jest'; import { HMToken__factory } from '@human-protocol/core/typechain-types'; -import { - Encryption, - EscrowClient, - OperatorUtils, - StorageClient, -} from '@human-protocol/sdk'; +import { Encryption, EscrowClient, OperatorUtils } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; import { ConfigService } from '@nestjs/config'; import { Test } from '@nestjs/testing'; @@ -30,6 +25,7 @@ import { ServerError, ValidationError, } from '../../common/errors'; +import { downloadFileFromUrl } from '../../common/utils/storage'; import { AssignmentEntity } from '../assignment/assignment.entity'; import { AssignmentRepository } from '../assignment/assignment.repository'; import { StorageService } from '../storage/storage.service'; @@ -49,13 +45,14 @@ jest.mock('@human-protocol/sdk', () => ({ OperatorUtils: { getOperator: jest.fn(), }, - StorageClient: { - downloadFileFromUrl: jest.fn(), - }, Encryption: { build: jest.fn(), }, })); +jest.mock('../../common/utils/storage', () => ({ + ...jest.requireActual('../../common/utils/storage'), + downloadFileFromUrl: jest.fn(), +})); jest.mock('minio', () => { class Client { putObject = jest.fn(); @@ -446,6 +443,7 @@ describe('JobService', () => { }); describe('solveJob', () => { + const downloadFileFromUrlMock = jest.mocked(downloadFileFromUrl); const assignment = { id: 1, jobId: 1, @@ -484,9 +482,7 @@ describe('JobService', () => { storageService.downloadJobSolutions = jest.fn().mockResolvedValueOnce([]); - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValueOnce(manifest); + downloadFileFromUrlMock.mockResolvedValueOnce(manifest); const solutionsUrl = 'http://localhost:9000/solution/0x1234567890123456789012345678901234567890-1.json'; @@ -551,9 +547,7 @@ describe('JobService', () => { }, ]); - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValueOnce(manifest); + downloadFileFromUrlMock.mockResolvedValueOnce(manifest); (Encryption.build as any).mockImplementation(() => ({ decrypt: jest.fn().mockResolvedValue(JSON.stringify(manifest)), @@ -586,9 +580,7 @@ describe('JobService', () => { }, ]); - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValueOnce(manifest); + downloadFileFromUrlMock.mockResolvedValueOnce(manifest); (Encryption.build as any).mockImplementation(() => ({ decrypt: jest.fn().mockResolvedValue(JSON.stringify(manifest)), diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts index 40bbae2104..27646027f3 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts @@ -7,10 +7,10 @@ import { Encryption, EncryptionUtils, EscrowClient, - StorageClient, } from '@human-protocol/sdk'; import { Inject, Injectable } from '@nestjs/common'; +import { downloadFileFromUrl } from '../../common/utils/storage'; import { PGPConfigService } from '../../common/config/pgp-config.service'; import { ErrorAssignment, ErrorJob } from '../../common/constant/errors'; import { SortDirection } from '../../common/enums/collection'; @@ -348,8 +348,7 @@ export class JobService { let manifest: ManifestDto | null = null; try { - const manifestEncrypted = - await StorageClient.downloadFileFromUrl(manifestUrl); + const manifestEncrypted = await downloadFileFromUrl(manifestUrl); if ( typeof manifestEncrypted === 'string' && diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.spec.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.spec.ts index a8d561b7b9..0f35c5e1bb 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.spec.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.spec.ts @@ -2,7 +2,6 @@ import { ChainId, Encryption, EncryptionUtils, - StorageClient, EscrowClient, KVStoreUtils, } from '@human-protocol/sdk'; @@ -13,12 +12,10 @@ import { Web3Service } from '../web3/web3.service'; import { ConfigService } from '@nestjs/config'; import { S3ConfigService } from '../../common/config/s3-config.service'; import { PGPConfigService } from '../../common/config/pgp-config.service'; +import { downloadFileFromUrl } from '../../common/utils/storage'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), - StorageClient: { - downloadFileFromUrl: jest.fn(), - }, Encryption: { build: jest.fn(), }, @@ -33,6 +30,11 @@ jest.mock('@human-protocol/sdk', () => ({ }, })); +jest.mock('../../common/utils/storage', () => ({ + ...jest.requireActual('../../common/utils/storage'), + downloadFileFromUrl: jest.fn(), +})); + jest.mock('minio', () => { class Client { putObject = jest.fn(); @@ -125,6 +127,7 @@ describe('StorageService', () => { s3ConfigService.bucket, `${escrowAddress}-${chainId}.json`, 'encrypted', + undefined, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', @@ -159,6 +162,7 @@ describe('StorageService', () => { s3ConfigService.bucket, `${escrowAddress}-${chainId}.json`, 'encrypted', + undefined, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', @@ -239,6 +243,8 @@ describe('StorageService', () => { }); describe('downloadJobSolutions', () => { + const downloadFileFromUrlMock = jest.mocked(downloadFileFromUrl); + it('should download the encrypted file correctly', async () => { const workerAddress = '0x1234567890123456789012345678901234567891'; const escrowAddress = '0x1234567890123456789012345678901234567890'; @@ -252,9 +258,7 @@ describe('StorageService', () => { }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValue('encrypted-content'); + downloadFileFromUrlMock.mockResolvedValue('encrypted-content'); EncryptionUtils.isEncrypted = jest.fn().mockReturnValue(true); @@ -282,9 +286,7 @@ describe('StorageService', () => { }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValue(expectedJobFile); + downloadFileFromUrlMock.mockResolvedValue(expectedJobFile); EncryptionUtils.isEncrypted = jest.fn().mockReturnValue(false); @@ -299,9 +301,7 @@ describe('StorageService', () => { const escrowAddress = '0x1234567890123456789012345678901234567890'; const chainId = ChainId.LOCALHOST; - StorageClient.downloadFileFromUrl = jest - .fn() - .mockRejectedValue('Network error'); + downloadFileFromUrlMock.mockRejectedValue('Network error'); const solutionsFile = await storageService.downloadJobSolutions( escrowAddress, diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts index c885e0b6b1..4259033e6e 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts @@ -4,11 +4,11 @@ import { EncryptionUtils, EscrowClient, KVStoreUtils, - StorageClient, } from '@human-protocol/sdk'; import { Inject, Injectable } from '@nestjs/common'; import * as Minio from 'minio'; +import { downloadFileFromUrl } from '../../common/utils/storage'; import logger from '../../logger'; import { PGPConfigService } from '../../common/config/pgp-config.service'; import { S3ConfigService } from '../../common/config/s3-config.service'; @@ -49,7 +49,7 @@ export class StorageService { ): Promise { const url = this.getJobUrl(escrowAddress, chainId); try { - const fileContent = await StorageClient.downloadFileFromUrl(url); + const fileContent = await downloadFileFromUrl(url); if (EncryptionUtils.isEncrypted(fileContent)) { const encryption = await Encryption.build( this.pgpConfigService.privateKey!, @@ -120,6 +120,7 @@ export class StorageService { this.s3ConfigService.bucket, `${escrowAddress}-${chainId}.json`, fileToUpload, + undefined, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', diff --git a/packages/apps/fortune/recording-oracle/package.json b/packages/apps/fortune/recording-oracle/package.json index ae59f2e576..fb17499389 100644 --- a/packages/apps/fortune/recording-oracle/package.json +++ b/packages/apps/fortune/recording-oracle/package.json @@ -38,7 +38,7 @@ "dotenv": "^17.2.2", "helmet": "^7.1.0", "joi": "^17.13.3", - "minio": "7.1.3", + "minio": "8.0.6", "reflect-metadata": "^0.2.2", "rxjs": "^7.2.0" }, diff --git a/packages/apps/fortune/recording-oracle/scripts/setup-kv-store.ts b/packages/apps/fortune/recording-oracle/scripts/setup-kv-store.ts index 211d863379..0e4e9051cb 100644 --- a/packages/apps/fortune/recording-oracle/scripts/setup-kv-store.ts +++ b/packages/apps/fortune/recording-oracle/scripts/setup-kv-store.ts @@ -74,7 +74,7 @@ async function setupPublicKeyFile( throw new Error('Bucket does not exists'); } - await minioClient.putObject(s3Bucket, keyName, publicKey, { + await minioClient.putObject(s3Bucket, keyName, publicKey, undefined, { 'Content-Type': 'text/plain', 'Cache-Control': 'no-store', }); diff --git a/packages/apps/fortune/recording-oracle/src/common/utils/storage.ts b/packages/apps/fortune/recording-oracle/src/common/utils/storage.ts new file mode 100644 index 0000000000..104070d7af --- /dev/null +++ b/packages/apps/fortune/recording-oracle/src/common/utils/storage.ts @@ -0,0 +1,33 @@ +import axios from 'axios'; +import { HttpStatus } from '@nestjs/common'; + +export const isValidUrl = (maybeUrl: string): boolean => { + try { + const { protocol } = new URL(maybeUrl); + return protocol === 'http:' || protocol === 'https:'; + } catch { + return false; + } +}; + +export async function downloadFileFromUrl(url: string): Promise { + if (!isValidUrl(url)) { + throw new Error('Invalid URL string'); + } + + try { + const { data, status } = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (status !== HttpStatus.OK) { + throw new Error('Storage file not found'); + } + + return data; + } catch { + throw new Error('Storage file not found'); + } +} diff --git a/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts b/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts index 22455b4a07..e9094e4d21 100644 --- a/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts +++ b/packages/apps/fortune/recording-oracle/src/modules/job/job.service.spec.ts @@ -5,7 +5,6 @@ import { EscrowClient, EscrowStatus, KVStoreUtils, - StorageClient, } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; import { ConfigService } from '@nestjs/config'; @@ -36,6 +35,7 @@ import { Web3Service } from '../web3/web3.service'; import { WebhookDto } from '../webhook/webhook.dto'; import { JobService } from './job.service'; import { HMToken__factory } from '@human-protocol/core/typechain-types'; +import { downloadFileFromUrl } from '@/common/utils/storage'; jest.mock('minio', () => { class Client { @@ -51,19 +51,16 @@ jest.mock('minio', () => { return { Client }; }); +jest.mock('@/common/utils/storage', () => ({ + ...jest.requireActual('@/common/utils/storage'), + downloadFileFromUrl: jest.fn(), +})); + jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), EscrowClient: { build: jest.fn().mockImplementation(() => ({})), }, - StorageClient: jest.fn().mockImplementation(() => ({ - downloadFileFromUrl: jest.fn().mockResolvedValue( - JSON.stringify({ - submissionsRequired: 3, - requestType: JobRequestType.FORTUNE, - }), - ), - })), KVStoreUtils: { get: jest.fn(), getPublicKey: jest.fn().mockResolvedValue('publicKey'), @@ -75,6 +72,7 @@ jest.mock('@human-protocol/sdk', () => ({ describe('JobService', () => { let jobService: JobService; + const downloadFileFromUrlMock = jest.mocked(downloadFileFromUrl); jest .spyOn(Web3ConfigService.prototype, 'privateKey', 'get') @@ -193,9 +191,9 @@ describe('JobService', () => { getManifest: jest.fn().mockResolvedValue('http://example.com/manifest'), }; (EscrowClient.build as jest.Mock).mockResolvedValue(escrowClient); - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValue(JSON.stringify(invalidManifest)); + downloadFileFromUrlMock.mockResolvedValue( + JSON.stringify(invalidManifest), + ); const jobSolution: WebhookDto = { escrowAddress: MOCK_ADDRESS, @@ -221,9 +219,9 @@ describe('JobService', () => { getManifest: jest.fn().mockResolvedValue('http://example.com/manifest'), }; (EscrowClient.build as jest.Mock).mockResolvedValue(escrowClient); - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValue(JSON.stringify(invalidManifest)); + downloadFileFromUrlMock.mockResolvedValue( + JSON.stringify(invalidManifest), + ); EncryptionUtils.isEncrypted = jest.fn().mockReturnValueOnce(false); const jobSolution: WebhookDto = { @@ -283,8 +281,7 @@ describe('JobService', () => { }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); @@ -341,8 +338,7 @@ describe('JobService', () => { }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); @@ -403,8 +399,7 @@ describe('JobService', () => { }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); @@ -464,8 +459,7 @@ describe('JobService', () => { }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); @@ -555,8 +549,7 @@ describe('JobService', () => { solution: 'Solution 4', }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); @@ -633,8 +626,7 @@ describe('JobService', () => { solution: 'Solution 2', }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); @@ -716,8 +708,7 @@ describe('JobService', () => { solution: 'ass', }, ]; - StorageClient.downloadFileFromUrl = jest - .fn() + downloadFileFromUrlMock .mockResolvedValueOnce(JSON.stringify(manifest)) .mockResolvedValueOnce(JSON.stringify(existingJobSolutions)) .mockResolvedValue(JSON.stringify(exchangeJobSolutions)); diff --git a/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.spec.ts b/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.spec.ts index 855cd7911c..ad41fd39f9 100644 --- a/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.spec.ts +++ b/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.spec.ts @@ -4,7 +4,6 @@ import { EncryptionUtils, EscrowClient, KVStoreUtils, - StorageClient, } from '@human-protocol/sdk'; import { ConfigService } from '@nestjs/config'; import { Test } from '@nestjs/testing'; @@ -17,12 +16,10 @@ import { PGPConfigService } from '../../common/config/pgp-config.service'; import { S3ConfigService } from '../../common/config/s3-config.service'; import { Web3Service } from '../web3/web3.service'; import { StorageService } from './storage.service'; +import { downloadFileFromUrl } from '@/common/utils/storage'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), - StorageClient: { - downloadFileFromUrl: jest.fn(), - }, Encryption: { build: jest.fn(), }, @@ -37,6 +34,11 @@ jest.mock('@human-protocol/sdk', () => ({ }, })); +jest.mock('@/common/utils/storage', () => ({ + ...jest.requireActual('@/common/utils/storage'), + downloadFileFromUrl: jest.fn(), +})); + jest.mock('minio', () => { class Client { putObject = jest.fn(); @@ -133,6 +135,7 @@ describe('StorageService', () => { s3ConfigService.bucket, `${hash}.json`, 'encrypted', + undefined, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', @@ -211,6 +214,7 @@ describe('StorageService', () => { }); describe('download', () => { + const downloadFileFromUrlMock = jest.mocked(downloadFileFromUrl); it('should download the non encrypted file correctly', async () => { const exchangeAddress = '0x1234567890123456789012345678901234567892'; const workerAddress = '0x1234567890123456789012345678901234567891'; @@ -226,9 +230,7 @@ describe('StorageService', () => { ], }; - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValue(expectedJobFile); + downloadFileFromUrlMock.mockResolvedValue(expectedJobFile); EncryptionUtils.isEncrypted = jest.fn().mockReturnValue(false); const solutionsFile = await storageService.download(MOCK_FILE_URL); expect(solutionsFile).toStrictEqual(expectedJobFile); @@ -249,9 +251,7 @@ describe('StorageService', () => { ], }; - StorageClient.downloadFileFromUrl = jest - .fn() - .mockResolvedValue('encrypted-content'); + downloadFileFromUrlMock.mockResolvedValue('encrypted-content'); Encryption.build = jest.fn().mockResolvedValue({ decrypt: jest.fn().mockResolvedValue(JSON.stringify(expectedJobFile)), @@ -262,9 +262,7 @@ describe('StorageService', () => { }); it('should return empty array when file cannot be downloaded', async () => { - StorageClient.downloadFileFromUrl = jest - .fn() - .mockRejectedValue('Network error'); + downloadFileFromUrlMock.mockRejectedValue('Network error'); const solutionsFile = await storageService.download(MOCK_FILE_URL); expect(solutionsFile).toStrictEqual([]); diff --git a/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.ts b/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.ts index d2abeb58c8..330bc072b3 100644 --- a/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.ts +++ b/packages/apps/fortune/recording-oracle/src/modules/storage/storage.service.ts @@ -4,7 +4,6 @@ import { EncryptionUtils, EscrowClient, KVStoreUtils, - StorageClient, } from '@human-protocol/sdk'; import { Inject, Injectable } from '@nestjs/common'; import crypto from 'crypto'; @@ -15,6 +14,7 @@ import { ServerError, ValidationError } from '../../common/errors'; import { ISolution } from '../../common/interfaces/job'; import { SaveSolutionsDto } from '../job/job.dto'; import { Web3Service } from '../web3/web3.service'; +import { downloadFileFromUrl } from '../../common/utils/storage'; @Injectable() export class StorageService { @@ -42,7 +42,7 @@ export class StorageService { public async download(url: string): Promise { try { - const fileContent = await StorageClient.downloadFileFromUrl(url); + const fileContent = await downloadFileFromUrl(url); if ( typeof fileContent === 'string' && @@ -126,6 +126,7 @@ export class StorageService { this.s3ConfigService.bucket, `${hash}.json`, fileToUpload, + undefined, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', diff --git a/packages/apps/human-app/server/src/common/utils/storage.ts b/packages/apps/human-app/server/src/common/utils/storage.ts new file mode 100644 index 0000000000..104070d7af --- /dev/null +++ b/packages/apps/human-app/server/src/common/utils/storage.ts @@ -0,0 +1,33 @@ +import axios from 'axios'; +import { HttpStatus } from '@nestjs/common'; + +export const isValidUrl = (maybeUrl: string): boolean => { + try { + const { protocol } = new URL(maybeUrl); + return protocol === 'http:' || protocol === 'https:'; + } catch { + return false; + } +}; + +export async function downloadFileFromUrl(url: string): Promise { + if (!isValidUrl(url)) { + throw new Error('Invalid URL string'); + } + + try { + const { data, status } = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (status !== HttpStatus.OK) { + throw new Error('Storage file not found'); + } + + return data; + } catch { + throw new Error('Storage file not found'); + } +} diff --git a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts index d57967369f..6b513c8047 100644 --- a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts @@ -1,9 +1,4 @@ -import { - ChainId, - KVStoreKeys, - KVStoreUtils, - StorageClient, -} from '@human-protocol/sdk'; +import { ChainId, KVStoreKeys, KVStoreUtils } from '@human-protocol/sdk'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { HttpException, Inject, Injectable } from '@nestjs/common'; import { Cache } from 'cache-manager'; @@ -14,6 +9,7 @@ import { ORACLE_URL_CACHE_KEY, REPUTATION_ORACLE_PUBLIC_KEY, } from '../../common/constants/cache'; +import { downloadFileFromUrl } from '../../common/utils/storage'; @Injectable() export class KvStoreGateway { @@ -119,7 +115,7 @@ export class KvStoreGateway { address, JWT_KVSTORE_KEY, ); - publicKey = (await StorageClient.downloadFileFromUrl(url)) as string; + publicKey = (await downloadFileFromUrl(url)) as string; } catch (e) { if (e.toString().includes('Error: Invalid address')) { throw new HttpException( diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index c0b6502cab..5bf4ee45c4 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -59,7 +59,7 @@ "helmet": "^7.1.0", "joi": "^17.13.3", "json-stable-stringify": "^1.2.1", - "minio": "7.1.3", + "minio": "8.0.6", "nestjs-minio-client": "^2.2.0", "node-cache": "^5.1.2", "passport": "^0.7.0", diff --git a/packages/apps/job-launcher/server/scripts/setup-kv-store.ts b/packages/apps/job-launcher/server/scripts/setup-kv-store.ts index 63a790a62c..6a07297935 100644 --- a/packages/apps/job-launcher/server/scripts/setup-kv-store.ts +++ b/packages/apps/job-launcher/server/scripts/setup-kv-store.ts @@ -80,7 +80,7 @@ async function setupPublicKeyFile( throw new Error('Bucket does not exists'); } - await minioClient.putObject(s3Bucket, keyName, publicKey, { + await minioClient.putObject(s3Bucket, keyName, publicKey, undefined, { 'Content-Type': 'text/plain', 'Cache-Control': 'no-store', }); diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index 662b43e19f..91609c715b 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -7,7 +7,6 @@ import { KVStoreKeys, KVStoreUtils, NETWORKS, - StorageParams, } from '@human-protocol/sdk'; import { Inject, Injectable } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; @@ -85,7 +84,6 @@ import { Escrow, Escrow__factory } from '@human-protocol/core/typechain-types'; @Injectable() export class JobService { private readonly logger = logger.child({ context: JobService.name }); - public readonly storageParams: StorageParams; public readonly bucket: string; private cronJobRepository: CronJobRepository; diff --git a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts index 53d73cf339..5399c0be61 100644 --- a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts +++ b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts @@ -1,9 +1,4 @@ -import { - ChainId, - Encryption, - KVStoreUtils, - StorageParams, -} from '@human-protocol/sdk'; +import { ChainId, Encryption, KVStoreUtils } from '@human-protocol/sdk'; import { ValidationError as ClassValidationError, Injectable, @@ -72,7 +67,6 @@ import { @Injectable() export class ManifestService { - public readonly storageParams: StorageParams; public readonly bucket: string; constructor( diff --git a/packages/apps/job-launcher/server/src/modules/storage/storage.service.ts b/packages/apps/job-launcher/server/src/modules/storage/storage.service.ts index 523298f568..37f3558830 100644 --- a/packages/apps/job-launcher/server/src/modules/storage/storage.service.ts +++ b/packages/apps/job-launcher/server/src/modules/storage/storage.service.ts @@ -127,6 +127,7 @@ export class StorageService { this.s3ConfigService.bucket, fileKey, fileContents, + undefined, { 'Content-Type': contentType, 'Cache-Control': 'no-store', diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 7d494794ba..9a8dcf6733 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -59,7 +59,7 @@ "joi": "^17.13.3", "json-stable-stringify": "^1.2.1", "lodash": "^4.17.21", - "minio": "7.1.3", + "minio": "8.0.6", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "pg": "8.13.1", diff --git a/packages/apps/reputation-oracle/server/scripts/setup-kv-store.ts b/packages/apps/reputation-oracle/server/scripts/setup-kv-store.ts index 5165db585c..45ded5aea5 100644 --- a/packages/apps/reputation-oracle/server/scripts/setup-kv-store.ts +++ b/packages/apps/reputation-oracle/server/scripts/setup-kv-store.ts @@ -80,7 +80,7 @@ async function setupPublicKeyFile( throw new Error('Bucket does not exists'); } - await minioClient.putObject(s3Bucket, keyName, publicKey, { + await minioClient.putObject(s3Bucket, keyName, publicKey, undefined, { 'Content-Type': 'text/plain', 'Cache-Control': 'no-store', }); diff --git a/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts b/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts index 105b797ee2..6103f45ee0 100644 --- a/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts @@ -108,6 +108,7 @@ export class StorageService { this.s3ConfigService.bucket, fileName, content, + undefined, { 'Content-Type': contentType, 'Cache-Control': 'no-store', diff --git a/packages/sdk/python/human-protocol-sdk/Pipfile b/packages/sdk/python/human-protocol-sdk/Pipfile index b78efee08b..ae9b732d16 100644 --- a/packages/sdk/python/human-protocol-sdk/Pipfile +++ b/packages/sdk/python/human-protocol-sdk/Pipfile @@ -17,7 +17,6 @@ sphinx-autodoc-typehints = "*" [packages] cryptography = "*" -minio = "*" validators = "*" web3 = "*" aiohttp = "<4.0.0" # broken freeze in one of dependencies diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/__init__.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/__init__.py deleted file mode 100644 index d995f00412..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -""" -This modules contains an s3 client and utilities for files sharing. -""" - -from .storage_client import ( - StorageClient, - StorageClientError, - StorageFileNotFoundError, - Credentials, -) -from .storage_utils import StorageUtils diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_client.py deleted file mode 100644 index 47b2dec081..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_client.py +++ /dev/null @@ -1,379 +0,0 @@ -""" -This client enables to interact with S3 cloud storage services like Amazon S3 Bucket, -Google Cloud Storage and others. - -If credentials are not provided, anonymous access will be used (for downloading files). - -Code Example ------------- - -.. code-block:: python - - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - -Module ------- -""" - -import hashlib -import io -import json -import logging -import os -from typing import List, Optional -from warnings import warn - -from minio import Minio - -logging.getLogger("minio").setLevel(logging.INFO) - -DEBUG = "true" in os.getenv("DEBUG", "false").lower() -LOG = logging.getLogger("human_protocol_sdk.storage") -LOG.setLevel(logging.DEBUG if DEBUG else logging.INFO) - - -warn(f"The module {__name__} is deprecated.", DeprecationWarning, stacklevel=2) - - -class StorageClientError(Exception): - """ - Raises when some error happens when interacting with storage. - """ - - pass - - -class StorageFileNotFoundError(StorageClientError): - """ - Raises when some error happens when file is not found by its key. - """ - - pass - - -class Credentials: - """ - A class to represent the credentials required to authenticate with an S3-compatible service. - - Example:: - - credentials = Credentials( - access_key='my-access-key', - secret_key='my-secret-key' - ) - - """ - - def __init__(self, access_key: str, secret_key: str): - """ - Initializes a Credentials instance. - - :param access_key: The access key for the S3-compatible service. - :param secret_key: The secret key for the S3-compatible service. - """ - - self.access_key = access_key - self.secret_key = secret_key - - -class StorageClient: - """ - A class for downloading files from an S3-compatible service. - - :attribute: - - client (Minio): The S3-compatible client used for interacting with the service. - - :example: - .. code-block:: python - - # Download a list of files from an S3-compatible service - client = StorageClient( - endpoint_url='https://s3.us-west-2.amazonaws.com', - region='us-west-2', - credentials=Credentials( - access_key='my-access-key', - secret_key='my-secret-key' - ) - ) - files = ['file1.txt', 'file2.txt'] - bucket = 'my-bucket' - result_files = client.download_files(files=files, bucket=bucket) - - """ - - def __init__( - self, - endpoint_url: str, - region: Optional[str] = None, - credentials: Optional[Credentials] = None, - secure: Optional[bool] = True, - ): - """ - Initializes the StorageClient with the given endpoint_url, region, and credentials. - - If credentials are not provided, anonymous access will be used. - - :param endpoint_url: The URL of the S3-compatible service. - :param region: The region of the S3-compatible service. Defaults to None. - :param credentials: The credentials required to authenticate with the S3-compatible service. - Defaults to None for anonymous access. - :param secure: Flag to indicate to use secure (TLS) connection to S3 service or not. - Defaults to True. - """ - try: - self.client = ( - Minio( - region=region, - endpoint=endpoint_url, - secure=secure, - ) # anonymous access - if credentials is None - else Minio( - access_key=credentials.access_key, - secret_key=credentials.secret_key, - region=region, - endpoint=endpoint_url, - secure=secure, - ) # authenticated access - ) - self.endpoint = endpoint_url - self.secure = secure - except Exception as e: - LOG.error(f"Connection with S3 failed because of: {e}") - raise e - - def download_files(self, files: List[str], bucket: str) -> List[bytes]: - """ - Downloads a list of files from the specified S3-compatible bucket. - - :param files: A list of file keys to download. - :param bucket: The name of the S3-compatible bucket to download from. - - :return: A list of file contents (bytes) downloaded from the bucket. - - :raise StorageClientError: If an error occurs while downloading the files. - :raise StorageFileNotFoundError: If one of the specified files is not found in the bucket. - - :example: - .. code-block:: python - - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - result = storage_client.download_files( - files = ["file1.txt", "file2.txt"], - bucket = "my-bucket" - ) - """ - result_files = [] - for file in files: - try: - response = self.client.get_object(bucket_name=bucket, object_name=file) - result_files.append(response.read()) - except Exception as e: - if hasattr(e, "code") and str(e.code) == "NoSuchKey": - raise StorageFileNotFoundError("No object found - returning empty") - LOG.warning( - f"Reading the key {file} with S3 failed" f" because of: {str(e)}" - ) - raise StorageClientError(str(e)) - return result_files - - def upload_files(self, files: List[dict], bucket: str) -> List[dict]: - """ - Uploads a list of files to the specified S3-compatible bucket. - - :param files: A list of files to upload. - :param bucket: The name of the S3-compatible bucket to upload to. - - :return: List of dict with key, url, hash fields - - :raise StorageClientError: If an error occurs while uploading the files. - - :example: - .. code-block:: python - - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - result = storage_client.upload_files( - files = [{"file": "file content", "key": "file1.txt", "hash": "hash1"}], - bucket = "my-bucket" - ) - """ - result_files = [] - for file in files: - if "file" in file and "key" in file and "hash" in file: - data = file["file"] - hash = file["hash"] - key = file["key"] - else: - try: - artifact = json.dumps(file, sort_keys=True) - except Exception as e: - LOG.error("Can't extract the json from the object") - raise e - data = artifact.encode("utf-8") - hash = hashlib.sha1(data).hexdigest() - key = f"s3{hash}.json" - - url = ( - f"{'https' if self.secure else 'http'}://{self.endpoint}/{bucket}/{key}" - ) - file_exist = None - - try: - # check if file with same hash already exists in bucket - file_exist = self.client.stat_object( - bucket_name=bucket, object_name=key - ) - except Exception as e: - if hasattr(e, "code") and str(e.code) == "NoSuchKey": - # file does not exist in bucket, so upload it - pass - else: - LOG.warning( - f"Reading the key {key} in S3 failed" f" because of: {str(e)}" - ) - raise StorageClientError(str(e)) - - if not file_exist: - # file does not exist in bucket, so upload it - try: - self.client.put_object( - bucket_name=bucket, - object_name=key, - data=io.BytesIO(data), - length=len(data), - ) - LOG.debug(f"Uploaded to S3, key: {key}") - except Exception as e: - raise StorageClientError(str(e)) - - result_files.append({"key": key, "url": url, "hash": hash}) - - return result_files - - def bucket_exists(self, bucket: str) -> bool: - """ - Check if a given bucket exists. - - :param bucket: The name of the bucket to check. - - :return: True if the bucket exists, False otherwise. - - :raise StorageClientError: If an error occurs while checking the bucket. - - :example: - .. code-block:: python - - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - is_exists = storage_client.bucket_exists( - bucket = "my-bucket" - ) - """ - try: - return self.client.bucket_exists(bucket_name=bucket) - except Exception as e: - LOG.warning( - f"Checking the bucket {bucket} in S3 failed" f" because of: {str(e)}" - ) - raise StorageClientError(str(e)) - - def list_objects(self, bucket: str) -> List[str]: - """ - Return a list of all objects in a given bucket. - - :param bucket: The name of the bucket to list objects from. - - :return: A list of object keys in the given bucket. - - :raise StorageClientError: If an error occurs while listing the objects. - - :example: - .. code-block:: python - - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - result = storage_client.list_objects( - bucket = "my-bucket" - ) - """ - try: - objects = list(self.client.list_objects(bucket_name=bucket)) - if objects: - return [obj._object_name for obj in objects] - else: - return [] - except Exception as e: - LOG.warning(f"Listing objects in S3 failed because of: {str(e)}") - raise StorageClientError(str(e)) diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_utils.py deleted file mode 100644 index ee15eb2d9b..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/storage/storage_utils.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Utility class for storage-related operations. -""" - -import logging -import os -from warnings import warn - -import requests - -from human_protocol_sdk.storage.storage_client import StorageClientError -from human_protocol_sdk.utils import validate_url - -logging.getLogger("minio").setLevel(logging.INFO) - -DEBUG = "true" in os.getenv("DEBUG", "false").lower() -LOG = logging.getLogger("human_protocol_sdk.storage") -LOG.setLevel(logging.DEBUG if DEBUG else logging.INFO) - - -warn(f"The module {__name__} is deprecated.", DeprecationWarning, stacklevel=2) - - -class StorageUtils: - """ - Utility class for storage-related operations. - """ - - @staticmethod - def download_file_from_url(url: str) -> bytes: - """ - Downloads a file from the specified URL. - - :param url: The URL of the file to download. - - :return: The content of the downloaded file. - - :raise StorageClientError: If an error occurs while downloading the file. - - :example: - .. code-block:: python - - from human_protocol_sdk.storage import StorageUtils - - result = StorageUtils.download_file_from_url( - "https://www.example.com/file.txt" - ) - """ - if not validate_url(url): - raise StorageClientError(f"Invalid URL: {url}") - - try: - response = requests.get(url) - response.raise_for_status() - - return response.content - except Exception as e: - raise StorageClientError(str(e)) diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/__init__.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_client.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_client.py deleted file mode 100644 index e079badeb5..0000000000 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_client.py +++ /dev/null @@ -1,311 +0,0 @@ -import hashlib -import json -import random -import unittest -from unittest.mock import MagicMock, patch -import types -from minio import S3Error - -from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - StorageClientError, - StorageFileNotFoundError, -) - - -class TestCredentials(unittest.TestCase): - def test_credentials(self): - credentials = Credentials( - access_key="my-access-key", secret_key="my-secret-key" - ) - self.assertEqual(credentials.access_key, "my-access-key") - self.assertEqual(credentials.secret_key, "my-secret-key") - - -class TestStorageClient(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.endpoint_url = "s3.us-west-2.amazonaws.com" - cls.bucket = "my-bucket" - cls.files = ["file1.txt", "file2.txt"] - cls.region = "us-west-2" - cls.credentials = Credentials( - access_key="my-access-key", secret_key="my-secret-key" - ) - - def setUp(self): - self.client = StorageClient( - endpoint_url=self.endpoint_url, - region=self.region, - credentials=self.credentials, - ) - - def test_init_authenticated_access(self): - with patch("human_protocol_sdk.storage.storage_client.Minio") as mock_client: - client = StorageClient( - endpoint_url=self.endpoint_url, - region=self.region, - credentials=self.credentials, - ) - mock_client.assert_called_once_with( - access_key=self.credentials.access_key, - secret_key=self.credentials.secret_key, - region=self.region, - endpoint=self.endpoint_url, - secure=True, - ) - self.assertIsNotNone(client.client) - - def test_init_anonymous_access(self): - with patch("human_protocol_sdk.storage.storage_client.Minio") as mock_client: - client = StorageClient( - endpoint_url=self.endpoint_url, - ) - mock_client.assert_called_once() - self.assertEqual(mock_client.call_args_list[0].kwargs["region"], None) - self.assertEqual( - mock_client.call_args_list[0].kwargs["endpoint"], self.endpoint_url - ) - self.assertIsNotNone(client.client) - - def test_init_error(self): - # Connection error - with patch("human_protocol_sdk.storage.storage_client.Minio") as mock_client: - mock_client.side_effect = Exception("Connection error") - with self.assertRaises(Exception): - StorageClient(endpoint_url=self.endpoint_url) - - def test_download_files(self): - expected_result = [b"file1 contents", b"file2 contents"] - self.client.client.get_object = MagicMock( - side_effect=[ - MagicMock(read=MagicMock(return_value=expected_result[0])), - MagicMock(read=MagicMock(return_value=expected_result[1])), - ] - ) - result = self.client.download_files(files=self.files, bucket=self.bucket) - self.assertEqual(result, expected_result) - - def test_download_files_error(self): - self.client.client.get_object = MagicMock( - side_effect=S3Error( - code="NoSuchKey", - message="Key not found", - resource="", - request_id="", - host_id="", - response="", - ) - ) - with self.assertRaises(StorageFileNotFoundError): - self.client.download_files(files=self.files, bucket=self.bucket) - - def test_download_files_anonymous_error(self): - self.client.client.get_object = MagicMock( - side_effect=S3Error( - code="InvalidAccessKeyId", - message="Access denied", - resource="", - request_id="", - host_id="", - response="", - ) - ) - with self.assertRaises(StorageClientError): - self.client.download_files(files=self.files, bucket=self.bucket) - - def test_download_files_exception(self): - self.client.client.get_object = MagicMock( - side_effect=Exception("Connection error") - ) - with self.assertRaises(StorageClientError): - self.client.download_files(files=self.files, bucket=self.bucket) - - def test_upload_files(self): - file3 = "file3 content" - hash = hashlib.sha1(json.dumps("file3 content").encode("utf-8")).hexdigest() - key3 = f"s3{hash}.json" - - self.client.client.stat_object = MagicMock( - side_effect=S3Error( - code="NoSuchKey", - message="Object does not exist", - resource="", - request_id="", - host_id="", - response="", - ) - ) - self.client.client.put_object = MagicMock() - result = self.client.upload_files(files=[file3], bucket=self.bucket) - self.assertEqual(result[0]["key"], key3) - self.assertEqual( - result[0]["url"], f"https://s3.us-west-2.amazonaws.com/my-bucket/{key3}" - ) - self.assertEqual(result[0]["hash"], hash) - - def test_upload_encrypted_files(self): - encrypted_file = "encrypted file content" - hash = hashlib.sha1(json.dumps(encrypted_file).encode("utf-8")).hexdigest() - encrypted_file_key = f"s3{hash}" - file = { - "file": encrypted_file.encode("utf-8"), - "hash": hash, - "key": encrypted_file_key, - } - - self.client.client.stat_object = MagicMock( - side_effect=S3Error( - code="NoSuchKey", - message="Object does not exist", - resource="", - request_id="", - host_id="", - response="", - ) - ) - self.client.client.put_object = MagicMock() - result = self.client.upload_files(files=[file], bucket=self.bucket) - self.assertEqual(result[0]["key"], encrypted_file_key) - self.assertEqual( - result[0]["url"], - f"https://s3.us-west-2.amazonaws.com/my-bucket/{encrypted_file_key}", - ) - self.assertEqual(result[0]["hash"], hash) - - def test_upload_files_exist(self): - file3 = "file3 content" - hash = hashlib.sha1(json.dumps("file3 content").encode("utf-8")).hexdigest() - key3 = f"s3{hash}.json" - - self.client.client.stat_object = MagicMock( - side_effect=[{"_object_name": "1234567890"}] - ) - self.client.client.put_object = MagicMock() - result = self.client.upload_files(files=[file3], bucket=self.bucket) - self.assertEqual(result[0]["key"], key3) - self.assertEqual( - result[0]["url"], f"https://s3.us-west-2.amazonaws.com/my-bucket/{key3}" - ) - self.assertEqual(result[0]["hash"], hash) - - def test_upload_files_error(self): - file3 = "file3 content" - - # HeadObject error - self.client.client.head_object = MagicMock( - side_effect=S3Error( - code="InvalidAccessKeyId", - message="Access denied", - resource="", - request_id="", - host_id="", - response="", - ) - ) - with self.assertRaises(StorageClientError): - self.client.upload_files(files=[file3], bucket=self.bucket) - - # PutObject error - self.client.client.upload_fileobj = MagicMock( - side_effect=S3Error( - code="InvalidAccessKeyId", - message="Access denied", - resource="", - request_id="", - host_id="", - response="", - ) - ) - with self.assertRaises(StorageClientError): - self.client.upload_files(files=[file3], bucket=self.bucket) - - def test_bucket_exists(self): - self.client.client.bucket_exists = MagicMock(side_effect=[True]) - result = self.client.bucket_exists(bucket=self.bucket) - self.assertEqual(result, True) - - def test_bucket_exists_anonymous(self): - client = StorageClient( - endpoint_url=self.endpoint_url, - ) - client.client.bucket_exists = MagicMock(side_effect=[True]) - result = client.bucket_exists(bucket=self.bucket) - self.assertEqual(result, True) - - def test_bucket_not_exists(self): - self.client.client.bucket_exists = MagicMock(side_effect=[False]) - result = self.client.bucket_exists(bucket=self.bucket) - self.assertEqual(result, False) - - def test_bucket_error(self): - self.client.client.bucket_exists = MagicMock( - side_effect=Exception("Connection error") - ) - with self.assertRaises(StorageClientError): - self.client.bucket_exists(bucket=self.bucket) - - def test_list_objects(self): - file1 = types.SimpleNamespace() - file2 = types.SimpleNamespace() - file1._object_name = "file1" - file2._object_name = "file2" - self.client.client.list_objects = MagicMock(side_effect=[[file1, file2]]) - result = self.client.list_objects(bucket=self.bucket) - self.assertEqual(result, ["file1", "file2"]) - - def test_list_objects_anonymous(self): - client = StorageClient( - endpoint_url=self.endpoint_url, - ) - file1 = types.SimpleNamespace() - file2 = types.SimpleNamespace() - file1._object_name = "file1" - file2._object_name = "file2" - client.client.list_objects = MagicMock(side_effect=[[file1, file2]]) - result = client.list_objects(bucket=self.bucket) - self.assertEqual(result, ["file1", "file2"]) - - def test_list_objects_empty(self): - self.client.client.list_objects = MagicMock(side_effect=[[]]) - result = self.client.list_objects(bucket=self.bucket) - self.assertEqual(result, []) - - def test_list_objects_error(self): - self.client.client.head_bucket = MagicMock( - side_effect=Exception("Connection error") - ) - with self.assertRaises(StorageClientError): - self.client.list_objects(bucket=self.bucket) - - def test_list_objects_length(self): - expected_length = random.randint(1, 10) - mock_client = MagicMock() - mock_client.list_objects.return_value = [ - types.SimpleNamespace(_object_name=f"file{i}") - for i in range(expected_length) - ] - with patch( - "human_protocol_sdk.storage.storage_client.Minio", return_value=mock_client - ): - client = StorageClient(endpoint_url="https://example.com", credentials=None) - object_list = client.list_objects(bucket="my-bucket") - self.assertEqual(len(object_list), expected_length) - - def test_list_objects_length_error(self): - expected_length = random.randint(1, 10) - mock_client = MagicMock() - mock_client.list_objects.return_value = [ - types.SimpleNamespace(_object_name=f"file{i}") - for i in range(expected_length) - ] - with patch( - "human_protocol_sdk.storage.storage_client.Minio", return_value=mock_client - ): - client = StorageClient(endpoint_url="https://example.com", credentials=None) - object_list = client.list_objects(bucket="my-bucket") - if len(object_list) != expected_length: - raise AssertionError( - f"Expected {expected_length} objects, but found {len(object_list)}" - ) diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_utils.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_utils.py deleted file mode 100644 index e8dab760db..0000000000 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/storage/test_storage_utils.py +++ /dev/null @@ -1,37 +0,0 @@ -import unittest -from unittest.mock import patch - -from human_protocol_sdk.storage import StorageUtils, StorageClientError -import requests - - -class TestStorageUtils(unittest.TestCase): - def test_download_file_from_url(self): - with patch("requests.get") as mock_get: - mock_response = mock_get.return_value - mock_response.raise_for_status.return_value = None - mock_response.content = b"Test file content" - url = "https://www.example.com/file.txt" - - result = StorageUtils.download_file_from_url(url) - - self.assertEqual(result, b"Test file content") - - def test_download_file_from_url_invalid_url(self): - url = "invalid_url" - - with self.assertRaises(StorageClientError) as cm: - StorageUtils.download_file_from_url(url) - self.assertEqual(f"Invalid URL: {url}", str(cm.exception)) - - def test_download_file_from_url_error(self): - with patch("requests.get") as mock_get: - url = "https://www.example.com/file.txt" - mock_response = mock_get.return_value - mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError( - f"Not Found for url: {url}", response=mock_response - ) - - with self.assertRaises(StorageClientError) as cm: - StorageUtils.download_file_from_url(url) - self.assertEqual(f"Not Found for url: {url}", str(cm.exception)) diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index 96a26132b8..fed510c51e 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -44,7 +44,6 @@ "graphql": "^16.8.1", "graphql-request": "^7.3.4", "graphql-tag": "^2.12.6", - "minio": "7.1.3", "openpgp": "^6.2.2", "secp256k1": "^5.0.1", "validator": "^13.12.0", diff --git a/packages/sdk/typescript/human-protocol-sdk/src/error.ts b/packages/sdk/typescript/human-protocol-sdk/src/error.ts index 3a2d61888d..f5cbe8fd4c 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/error.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/error.ts @@ -3,42 +3,6 @@ */ export const ErrorStakingMissing = new Error('Staking contract is missing'); -/** - * @constant {Error} - The Storage client not initialized. - */ -export const ErrorStorageClientNotInitialized = new Error( - 'Storage client not initialized' -); - -/** - * @constant {Error} - The Storage client does not exist. - */ -export const ErrorStorageClientNotExists = new Error( - 'Storage client does not exist' -); - -/** - * @constant {Error} - The Storage credentials are missing. - */ -export const ErrorStorageCredentialsMissing = new Error( - 'Storage credentials are missing' -); - -/** - * @constant {Error} - The Storage bucket not found. - */ -export const ErrorStorageBucketNotFound = new Error('Bucket not found'); - -/** - * @constant {Error} - The Storage file not found. - */ -export const ErrorStorageFileNotFound = new Error('File not found'); - -/** - * @constant {Error} - The Storage file not uploaded. - */ -export const ErrorStorageFileNotUploaded = new Error('File not uploaded'); - /** * @constant {Error} - The KVStore key cannot be empty. */ diff --git a/packages/sdk/typescript/human-protocol-sdk/src/index.ts b/packages/sdk/typescript/human-protocol-sdk/src/index.ts index 047bfb6782..15a363bae2 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/index.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/index.ts @@ -1,5 +1,4 @@ import { StakingClient, StakingUtils } from './staking'; -import { StorageClient } from './storage'; import { KVStoreClient, KVStoreUtils } from './kvstore'; import { EscrowClient, EscrowUtils } from './escrow'; import { StatisticsClient } from './statistics'; @@ -27,7 +26,6 @@ export { export { StakingClient, - StorageClient, KVStoreClient, KVStoreUtils, EscrowClient, diff --git a/packages/sdk/typescript/human-protocol-sdk/src/storage.ts b/packages/sdk/typescript/human-protocol-sdk/src/storage.ts deleted file mode 100644 index 81656fcaf9..0000000000 --- a/packages/sdk/typescript/human-protocol-sdk/src/storage.ts +++ /dev/null @@ -1,313 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import axios from 'axios'; -import crypto from 'crypto'; -import * as Minio from 'minio'; -import { - ErrorInvalidUrl, - ErrorStorageBucketNotFound, - ErrorStorageClientNotInitialized, - ErrorStorageFileNotFound, - ErrorStorageFileNotUploaded, -} from './error'; -import { UploadFile, StorageCredentials, StorageParams } from './types'; -import { isValidUrl } from './utils'; -import { HttpStatus } from './constants'; - -/** - * - * @deprecated StorageClient is deprecated. Use Minio.Client directly. - * - * ## Introduction - * - * This client enables interacting with S3 cloud storage services like Amazon S3 Bucket, Google Cloud Storage, and others. - * - * The instance creation of `StorageClient` should be made using its constructor: - * - * ```ts - * constructor(params: StorageParams, credentials?: StorageCredentials) - * ``` - * - * > If credentials are not provided, it uses anonymous access to the bucket for downloading files. - * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example - * - * ```ts - * import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - * - * const credentials: StorageCredentials = { - * accessKey: 'ACCESS_KEY', - * secretKey: 'SECRET_KEY', - * }; - * const params: StorageParams = { - * endPoint: 'http://localhost', - * port: 9000, - * useSSL: false, - * region: 'us-east-1' - * }; - * - * const storageClient = new StorageClient(params, credentials); - * ``` - */ -export class StorageClient { - private client: Minio.Client; - private clientParams: StorageParams; - - /** - * **Storage client constructor** - * - * @param {StorageParams} params - Cloud storage params - * @param {StorageCredentials} credentials - Optional. Cloud storage access data. If credentials are not provided - use anonymous access to the bucket - */ - constructor(params: StorageParams, credentials?: StorageCredentials) { - try { - this.clientParams = params; - - this.client = new Minio.Client({ - ...params, - accessKey: credentials?.accessKey ?? '', - secretKey: credentials?.secretKey ?? '', - }); - } catch { - throw ErrorStorageClientNotInitialized; - } - } - - /** - * This function downloads files from a bucket. - * - * @param {string[]} keys Array of filenames to download. - * @param {string} bucket Bucket name. - * @returns {Promise} Returns an array of JSON files downloaded and parsed into objects. - * - * **Code example** - * - * ```ts - * import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - * - * const params: StorageParams = { - * endPoint: 'http://localhost', - * port: 9000, - * useSSL: false, - * region: 'us-east-1' - * }; - * - * const storageClient = new StorageClient(params); - * - * const keys = ['file1.json', 'file2.json']; - * const files = await storageClient.downloadFiles(keys, 'bucket-name'); - * ``` - */ - public async downloadFiles(keys: string[], bucket: string): Promise { - const isBucketExists = await this.client.bucketExists(bucket); - if (!isBucketExists) { - throw ErrorStorageBucketNotFound; - } - - return Promise.all( - keys.map(async (key) => { - try { - const response = await this.client.getObject(bucket, key); - const content = response?.read(); - - return { key, content: JSON.parse(content?.toString('utf-8') || '') }; - } catch { - throw ErrorStorageFileNotFound; - } - }) - ); - } - - /** - * This function downloads files from a URL. - * - * @param {string} url URL of the file to download. - * @returns {Promise} Returns the JSON file downloaded and parsed into an object. - * - * **Code example** - * - * ```ts - * import { StorageClient } from '@human-protocol/sdk'; - * - * const file = await StorageClient.downloadFileFromUrl('http://localhost/file.json'); - * ``` - */ - public static async downloadFileFromUrl(url: string): Promise { - if (!isValidUrl(url)) { - throw ErrorInvalidUrl; - } - - try { - const { data, status } = await axios.get(url, { - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (status !== HttpStatus.OK) { - throw ErrorStorageFileNotFound; - } - - return data; - } catch { - throw ErrorStorageFileNotFound; - } - } - - /** - * This function uploads files to a bucket. - * - * @param {any[]} files Array of objects to upload serialized into JSON. - * @param {string} bucket Bucket name. - * @returns {Promise} Returns an array of uploaded file metadata. - * - * **Code example** - * - * ```ts - * import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - * - * const credentials: StorageCredentials = { - * accessKey: 'ACCESS_KEY', - * secretKey: 'SECRET_KEY', - * }; - * const params: StorageParams = { - * endPoint: 'http://localhost', - * port: 9000, - * useSSL: false, - * region: 'us-east-1' - * }; - * - * const storageClient = new StorageClient(params, credentials); - * const file1 = { name: 'file1', description: 'description of file1' }; - * const file2 = { name: 'file2', description: 'description of file2' }; - * const files = [file1, file2]; - * const uploadedFiles = await storageClient.uploadFiles(files, 'bucket-name'); - * ``` - */ - public async uploadFiles( - files: any[], - bucket: string - ): Promise { - const isBucketExists = await this.client.bucketExists(bucket); - if (!isBucketExists) { - throw ErrorStorageBucketNotFound; - } - - return Promise.all( - files.map(async (file) => { - const content = JSON.stringify(file); - - const hash = crypto.createHash('sha1').update(content).digest('hex'); - const key = `s3${hash}.json`; - - try { - await this.client.putObject(bucket, key, content, { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - }); - - return { - key, - url: `${this.clientParams.useSSL ? 'https' : 'http'}://${ - this.clientParams.endPoint - }${ - this.clientParams.port ? `:${this.clientParams.port}` : '' - }/${bucket}/${key}`, - hash, - }; - } catch { - throw ErrorStorageFileNotUploaded; - } - }) - ); - } - - /** - * This function checks if a bucket exists. - * - * @param {string} bucket Bucket name. - * @returns {Promise} Returns `true` if exists, `false` if it doesn't. - * - * **Code example** - * - * ```ts - * import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - * - * const credentials: StorageCredentials = { - * accessKey: 'ACCESS_KEY', - * secretKey: 'SECRET_KEY', - * }; - * const params: StorageParams = { - * endPoint: 'http://localhost', - * port: 9000, - * useSSL: false, - * region: 'us-east-1' - * }; - * - * const storageClient = new StorageClient(params, credentials); - * const exists = await storageClient.bucketExists('bucket-name'); - * ``` - */ - public async bucketExists(bucket: string): Promise { - return this.client.bucketExists(bucket); - } - - /** - * This function lists all file names contained in the bucket. - * - * @param {string} bucket Bucket name. - * @returns {Promise} Returns the list of file names contained in the bucket. - * - * **Code example** - * - * ```ts - * import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - * - * const credentials: StorageCredentials = { - * accessKey: 'ACCESS_KEY', - * secretKey: 'SECRET_KEY', - * }; - * const params: StorageParams = { - * endPoint: 'http://localhost', - * port: 9000, - * useSSL: false, - * region: 'us-east-1' - * }; - * - * const storageClient = new StorageClient(params, credentials); - * const fileNames = await storageClient.listObjects('bucket-name'); - * ``` - */ - public async listObjects(bucket: string): Promise { - const isBucketExists = await this.client.bucketExists(bucket); - if (!isBucketExists) { - throw ErrorStorageBucketNotFound; - } - - try { - return new Promise((resolve, reject) => { - const keys: string[] = []; - const stream = this.client.listObjectsV2(bucket, '', true, ''); - - stream.on('data', (obj: { name: string }) => keys.push(obj.name)); - stream.on('error', reject); - stream.on('end', () => { - resolve(keys); - }); - }); - } catch (e) { - throw new Error(String(e)); - } - } -} diff --git a/packages/sdk/typescript/human-protocol-sdk/src/types.ts b/packages/sdk/typescript/human-protocol-sdk/src/types.ts index 14497c4bc5..6d5ae3a7ba 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/types.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/types.ts @@ -36,63 +36,6 @@ export enum EscrowStatus { ToCancel, } -/** - * AWS/GCP cloud storage access data - * @readonly - * @deprecated StorageClient is deprecated. Use Minio.Client directly. - */ -export type StorageCredentials = { - /** - * Access Key - */ - accessKey: string; - /** - * Secret Key - */ - secretKey: string; -}; - -/** - * @deprecated StorageClient is deprecated. Use Minio.Client directly. - */ -export type StorageParams = { - /** - * Request endPoint - */ - endPoint: string; - /** - * Enable secure (HTTPS) access. Default value set to false - */ - useSSL: boolean; - /** - * Region - */ - region?: string; - /** - * TCP/IP port number. Default value set to 80 for HTTP and 443 for HTTPs - */ - port?: number; -}; - -/** - * Upload file data - * @readonly - */ -export type UploadFile = { - /** - * Uploaded object key - */ - key: string; - /** - * Uploaded object URL - */ - url: string; - /** - * Hash of uploaded object key - */ - hash: string; -}; - /** * Network data */ diff --git a/packages/sdk/typescript/human-protocol-sdk/test/storage.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/storage.test.ts deleted file mode 100644 index 6c1988c700..0000000000 --- a/packages/sdk/typescript/human-protocol-sdk/test/storage.test.ts +++ /dev/null @@ -1,400 +0,0 @@ -// Create a Minio.Client mock -vi.mock('minio', () => { - class Client { - getObject = vi.fn().mockImplementation(() => { - const read = () => { - return JSON.stringify({ key: STORAGE_TEST_FILE_VALUE }); - }; - return Promise.resolve({ read }); - }); // getObject mock - putObject = vi.fn(); // putObject mock - bucketExists = vi.fn().mockImplementation((bucketName) => { - // Add conditional logic here based on the test scenario - if (bucketName === STORAGE_FAKE_BUCKET) { - return Promise.resolve(false); // Return false for fake scenario - } else { - return Promise.resolve(true); // Return true for other scenarios - } - }); - } - - // Return Minio.Client mock - return { Client }; -}); - -import { describe, test, expect, vi, beforeAll } from 'vitest'; -import axios from 'axios'; -import crypto from 'crypto'; -import { - DEFAULT_ENDPOINT, - DEFAULT_PORT, - DEFAULT_PUBLIC_BUCKET, - DEFAULT_REGION, - DEFAULT_USE_SSL, - HttpStatus, - StorageCredentials, - StorageParams, -} from '../src'; -import { - ErrorInvalidUrl, - ErrorStorageFileNotFound, - ErrorStorageFileNotUploaded, -} from '../src/error'; -import { StorageClient } from '../src/storage'; -import { - FAKE_URL, - STORAGE_FAKE_BUCKET, - STORAGE_TEST_ACCESS_KEY, - STORAGE_TEST_FILE_VALUE, - STORAGE_TEST_FILE_VALUE_2, - STORAGE_TEST_SECRET_KEY, -} from './utils/constants'; - -describe('Storage tests', () => { - describe('Client initialization', () => { - test('should set correct credentials', async () => { - const storageCredentials: StorageCredentials = { - accessKey: STORAGE_TEST_ACCESS_KEY, - secretKey: STORAGE_TEST_SECRET_KEY, - }; - - expect(storageCredentials.accessKey).toEqual(STORAGE_TEST_ACCESS_KEY); - expect(storageCredentials.secretKey).toEqual(STORAGE_TEST_SECRET_KEY); - }); - - test('should set correct params', async () => { - const storageParams: StorageParams = { - endPoint: DEFAULT_ENDPOINT, - port: DEFAULT_PORT, - useSSL: DEFAULT_USE_SSL, - region: DEFAULT_REGION, - }; - - expect(storageParams.endPoint).toEqual(DEFAULT_ENDPOINT); - expect(storageParams.port).toEqual(DEFAULT_PORT); - expect(storageParams.useSSL).toEqual(false); - expect(storageParams.region).toEqual(DEFAULT_REGION); - }); - - test('should init client with empty credentials', async () => { - const storageParams: StorageParams = { - endPoint: DEFAULT_ENDPOINT, - port: DEFAULT_PORT, - useSSL: DEFAULT_USE_SSL, - }; - - const storageClient = new StorageClient(storageParams); - - expect(storageClient).toBeInstanceOf(StorageClient); - }); - }); - - describe('Client anonymous access', () => { - let storageClient: StorageClient; - - beforeAll(async () => { - const storageParams: StorageParams = { - endPoint: DEFAULT_ENDPOINT, - port: DEFAULT_PORT, - useSSL: DEFAULT_USE_SSL, - }; - - storageClient = new StorageClient(storageParams); - }); - - test('should return the bucket exists', async () => { - const isExists = await storageClient.bucketExists(DEFAULT_PUBLIC_BUCKET); - expect(isExists).toEqual(true); - }); - - test('should return the bucket does not exist', async () => { - const isExists = await storageClient.bucketExists(STORAGE_FAKE_BUCKET); - expect(isExists).toEqual(false); - }); - - test('should upload the file with success', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - - const uploadedResults = await storageClient.uploadFiles( - [file], - DEFAULT_PUBLIC_BUCKET - ); - - const hash = crypto - .createHash('sha1') - .update(JSON.stringify(file)) - .digest('hex'); - const key = `s3${hash}.json`; - - expect(storageClient['client'].putObject).toHaveBeenCalledWith( - DEFAULT_PUBLIC_BUCKET, - key, - JSON.stringify(file), - { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - } - ); - expect(uploadedResults[0].key).toEqual(key); - expect(uploadedResults[0].url).toEqual( - `http://${DEFAULT_ENDPOINT}:${DEFAULT_PORT}/${DEFAULT_PUBLIC_BUCKET}/${key}` - ); - expect(uploadedResults[0].hash).toEqual(hash); - }); - - test('should not upload the file with an error', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - vi.spyOn(storageClient, 'uploadFiles').mockImplementation(() => { - throw ErrorStorageFileNotUploaded; - }); - expect(() => - storageClient.uploadFiles([file], DEFAULT_PUBLIC_BUCKET) - ).toThrow(ErrorStorageFileNotUploaded); - }); - - test('should download the files with success', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - - const hash = crypto - .createHash('sha1') - .update(JSON.stringify(file)) - .digest('hex'); - const key = `s3${hash}.json`; - - const downloadedResults = await storageClient.downloadFiles( - [key], - DEFAULT_PUBLIC_BUCKET - ); - - expect(storageClient['client'].getObject).toHaveBeenCalledWith( - DEFAULT_PUBLIC_BUCKET, - key - ); - expect(downloadedResults[0].key).toEqual(key); - expect(downloadedResults[0].content).toEqual(file); - }); - - test('should not download the files with an error', async () => { - vi.spyOn(storageClient, 'downloadFiles').mockImplementation(() => { - throw ErrorStorageFileNotFound; - }); - expect(() => - storageClient.downloadFiles( - [STORAGE_TEST_FILE_VALUE], - DEFAULT_PUBLIC_BUCKET - ) - ).toThrow(ErrorStorageFileNotFound); - }); - - test('should fail URL validation', async () => { - await expect(StorageClient.downloadFileFromUrl(FAKE_URL)).rejects.toThrow( - ErrorInvalidUrl - ); - }); - - test('should download the file from URL with success', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - - vi.spyOn(axios, 'get').mockImplementation(() => - Promise.resolve({ data: file, status: HttpStatus.OK }) - ); - - const hash = crypto - .createHash('sha1') - .update(JSON.stringify(file)) - .digest('hex'); - const url = `http://${DEFAULT_ENDPOINT}:${DEFAULT_PORT}/${DEFAULT_PUBLIC_BUCKET}/${hash}.json`; - - const result = await StorageClient.downloadFileFromUrl(url); - expect(result).toEqual(file); - }); - - test('should not download the file from URL with an error', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - - const hash = crypto - .createHash('sha1') - .update(JSON.stringify(file)) - .digest('hex'); - const url = `http://${DEFAULT_ENDPOINT}:${DEFAULT_PORT}/${DEFAULT_PUBLIC_BUCKET}/${hash}.json`; - - vi.spyOn(StorageClient, 'downloadFileFromUrl').mockImplementation(() => { - throw ErrorStorageFileNotFound; - }); - expect(() => StorageClient.downloadFileFromUrl(url)).toThrow( - ErrorStorageFileNotFound - ); - }); - - test('should return a list of objects with success', async () => { - const file1 = { key: STORAGE_TEST_FILE_VALUE }; - const hash1 = crypto - .createHash('sha1') - .update(JSON.stringify(file1)) - .digest('hex'); - const key1 = `s3${hash1}.json`; - - const file2 = { key: STORAGE_TEST_FILE_VALUE_2 }; - const hash2 = crypto - .createHash('sha1') - .update(JSON.stringify(file2)) - .digest('hex'); - const key2 = `s3${hash2}.json`; - - vi.spyOn(storageClient, 'listObjects').mockImplementation(() => - Promise.resolve([key1, key2]) - ); - - const results = await storageClient.listObjects(DEFAULT_PUBLIC_BUCKET); - - expect(results[0]).toEqual(key1); - expect(results[1]).toEqual(key2); - }); - - test('should not return a list of objects with an error', async () => { - vi.spyOn(storageClient, 'listObjects').mockImplementation(() => { - throw new Error(); - }); - expect(() => storageClient.listObjects(DEFAULT_PUBLIC_BUCKET)).toThrow( - new Error() - ); - }); - }); - - describe('Client with credentials', () => { - let storageClient: StorageClient; - - beforeAll(async () => { - const storageCredentials: StorageCredentials = { - accessKey: STORAGE_TEST_ACCESS_KEY, - secretKey: STORAGE_TEST_SECRET_KEY, - }; - - const storageParams: StorageParams = { - endPoint: DEFAULT_ENDPOINT, - port: DEFAULT_PORT, - useSSL: DEFAULT_USE_SSL, - }; - - storageClient = new StorageClient(storageParams, storageCredentials); - }); - - test('should return the bucket exists', async () => { - const isExists = await storageClient.bucketExists(DEFAULT_PUBLIC_BUCKET); - expect(isExists).toEqual(true); - }); - - test('should return the bucket does not exist', async () => { - const isExists = await storageClient.bucketExists(STORAGE_FAKE_BUCKET); - expect(isExists).toEqual(false); - }); - - test('should upload the file with success', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - - const uploadedResults = await storageClient.uploadFiles( - [file], - DEFAULT_PUBLIC_BUCKET - ); - - const hash = crypto - .createHash('sha1') - .update(JSON.stringify(file)) - .digest('hex'); - const key = `s3${hash}.json`; - - expect(storageClient['client'].putObject).toHaveBeenCalledWith( - DEFAULT_PUBLIC_BUCKET, - key, - JSON.stringify(file), - { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - } - ); - expect(uploadedResults[0].key).toEqual(key); - expect(uploadedResults[0].url).toEqual( - `http://${DEFAULT_ENDPOINT}:${DEFAULT_PORT}/${DEFAULT_PUBLIC_BUCKET}/${key}` - ); - expect(uploadedResults[0].hash).toEqual(hash); - }); - - test('should not upload the file with an error', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - vi.spyOn(storageClient, 'uploadFiles').mockImplementation(() => { - throw ErrorStorageFileNotUploaded; - }); - expect(() => - storageClient.uploadFiles([file], DEFAULT_PUBLIC_BUCKET) - ).toThrow(ErrorStorageFileNotUploaded); - }); - - test('should download the file with success', async () => { - const file = { key: STORAGE_TEST_FILE_VALUE }; - - const hash = crypto - .createHash('sha1') - .update(JSON.stringify(file)) - .digest('hex'); - const key = `s3${hash}.json`; - - const downloadedResults = await storageClient.downloadFiles( - [key], - DEFAULT_PUBLIC_BUCKET - ); - - expect(storageClient['client'].getObject).toHaveBeenCalledWith( - DEFAULT_PUBLIC_BUCKET, - key - ); - expect(downloadedResults[0].key).toEqual(key); - expect(downloadedResults[0].content).toEqual(file); - }); - - test('should not download the file with an error', async () => { - vi.spyOn(storageClient, 'downloadFiles').mockImplementation(() => { - throw ErrorStorageFileNotFound; - }); - expect(() => - storageClient.downloadFiles( - [STORAGE_TEST_FILE_VALUE], - DEFAULT_PUBLIC_BUCKET - ) - ).toThrow(ErrorStorageFileNotFound); - }); - - test('should return a list of objects with success', async () => { - const file1 = { key: STORAGE_TEST_FILE_VALUE }; - const hash1 = crypto - .createHash('sha1') - .update(JSON.stringify(file1)) - .digest('hex'); - const key1 = `s3${hash1}.json`; - - const file2 = { key: STORAGE_TEST_FILE_VALUE_2 }; - const hash2 = crypto - .createHash('sha1') - .update(JSON.stringify(file2)) - .digest('hex'); - const key2 = `s3${hash2}.json`; - - vi.spyOn(storageClient, 'listObjects').mockImplementation(() => - Promise.resolve([key1, key2]) - ); - - const results = await storageClient.listObjects(DEFAULT_PUBLIC_BUCKET); - - expect(results[0]).toEqual(key1); - expect(results[1]).toEqual(key2); - }); - - test('should not return a list of objects with an error', async () => { - vi.spyOn(storageClient, 'listObjects').mockImplementation(() => { - throw new Error(); - }); - expect(() => storageClient.listObjects(DEFAULT_PUBLIC_BUCKET)).toThrow( - new Error() - ); - }); - }); -}); diff --git a/yarn.lock b/yarn.lock index b951ec5945..1e635094d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -327,7 +327,7 @@ __metadata: jest: "npm:30.2.0" joi: "npm:^17.13.3" jsonwebtoken: "npm:^9.0.2" - minio: "npm:7.1.3" + minio: "npm:8.0.6" passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" pg: "npm:8.13.1" @@ -372,7 +372,7 @@ __metadata: helmet: "npm:^7.1.0" jest: "npm:^30.2.0" joi: "npm:^17.13.3" - minio: "npm:7.1.3" + minio: "npm:8.0.6" prettier: "npm:^3.4.2" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" @@ -638,7 +638,7 @@ __metadata: jest: "npm:30.2.0" joi: "npm:^17.13.3" json-stable-stringify: "npm:^1.2.1" - minio: "npm:7.1.3" + minio: "npm:8.0.6" nestjs-minio-client: "npm:^2.2.0" node-cache: "npm:^5.1.2" passport: "npm:^0.7.0" @@ -714,7 +714,7 @@ __metadata: joi: "npm:^17.13.3" json-stable-stringify: "npm:^1.2.1" lodash: "npm:^4.17.21" - minio: "npm:7.1.3" + minio: "npm:8.0.6" nock: "npm:^14.0.3" passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" @@ -4989,7 +4989,6 @@ __metadata: graphql: "npm:^16.8.1" graphql-request: "npm:^7.3.4" graphql-tag: "npm:^2.12.6" - minio: "npm:7.1.3" openpgp: "npm:^6.2.2" prettier: "npm:^3.4.2" secp256k1: "npm:^5.0.1" @@ -15106,6 +15105,13 @@ __metadata: languageName: node linkType: hard +"buffer-crc32@npm:^1.0.0": + version: 1.0.0 + resolution: "buffer-crc32@npm:1.0.0" + checksum: 10c0/8b86e161cee4bb48d5fa622cbae4c18f25e4857e5203b89e23de59e627ab26beb82d9d7999f2b8de02580165f61f83f997beaf02980cdf06affd175b651921ab + languageName: node + linkType: hard + "buffer-equal-constant-time@npm:^1.0.1": version: 1.0.1 resolution: "buffer-equal-constant-time@npm:1.0.1" @@ -23781,6 +23787,28 @@ __metadata: languageName: node linkType: hard +"minio@npm:8.0.6": + version: 8.0.6 + resolution: "minio@npm:8.0.6" + dependencies: + async: "npm:^3.2.4" + block-stream2: "npm:^2.1.0" + browser-or-node: "npm:^2.1.1" + buffer-crc32: "npm:^1.0.0" + eventemitter3: "npm:^5.0.1" + fast-xml-parser: "npm:^4.4.1" + ipaddr.js: "npm:^2.0.1" + lodash: "npm:^4.17.21" + mime-types: "npm:^2.1.35" + query-string: "npm:^7.1.3" + stream-json: "npm:^1.8.0" + through2: "npm:^4.0.2" + web-encoding: "npm:^1.1.5" + xml2js: "npm:^0.5.0 || ^0.6.2" + checksum: 10c0/7b10b1d780f300d1ac8881be32e9b5a1d172f9c3e72bfb86f966d085746aa5e5aa9c54c41d728ba00d8cd8c4969ac219214c5e763d1f7918f53f1081fef1a19a + languageName: node + linkType: hard + "minipass-collect@npm:^2.0.1": version: 2.0.1 resolution: "minipass-collect@npm:2.0.1" @@ -28446,7 +28474,7 @@ __metadata: languageName: node linkType: hard -"stream-json@npm:^1.9.1": +"stream-json@npm:^1.8.0, stream-json@npm:^1.9.1": version: 1.9.1 resolution: "stream-json@npm:1.9.1" dependencies: @@ -31743,7 +31771,7 @@ __metadata: languageName: node linkType: hard -"xml2js@npm:^0.6.2": +"xml2js@npm:^0.5.0 || ^0.6.2, xml2js@npm:^0.6.2": version: 0.6.2 resolution: "xml2js@npm:0.6.2" dependencies: From ac581f35baf13fdc89c57f16e002350ae635e1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Thu, 11 Dec 2025 15:10:47 +0100 Subject: [PATCH 03/21] [Job Launcher][Server] Fix webhook on escrow creation (#3714) --- .../server/src/modules/job/job.service.spec.ts | 17 ++++++++++++++++- .../server/src/modules/job/job.service.ts | 13 +++++++++++++ .../src/modules/storage/storage.service.spec.ts | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts index b0c635ffd0..fddeddbac0 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts @@ -27,7 +27,11 @@ import { JobStatusFilter, } from '../../common/enums/job'; import { PaymentCurrency, PaymentType } from '../../common/enums/payment'; -import { EventType, OracleType } from '../../common/enums/webhook'; +import { + EventType, + OracleType, + WebhookStatus, +} from '../../common/enums/webhook'; import { ConflictError, NotFoundError, @@ -885,6 +889,17 @@ describe('JobService', () => { status: JobStatus.LAUNCHED, escrowAddress, }); + expect(mockWebhookRepository.createUnique).toHaveBeenCalledWith({ + chainId: jobEntity.chainId, + escrowAddress, + eventType: EventType.ESCROW_CREATED, + oracleType: OracleType.FORTUNE, + hasSignature: true, + oracleAddress: jobEntity.exchangeOracle, + retriesCount: 0, + waitUntil: expect.any(Date), + status: WebhookStatus.PENDING, + }); getOracleFeeSpy.mockRestore(); }); diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index 91609c715b..9f970ae77b 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -67,6 +67,7 @@ import { StorageService } from '../storage/storage.service'; import { UserEntity } from '../user/user.entity'; import { Web3Service } from '../web3/web3.service'; import { WebhookDataDto } from '../webhook/webhook.dto'; +import { WebhookEntity } from '../webhook/webhook.entity'; import { WebhookRepository } from '../webhook/webhook.repository'; import { WhitelistService } from '../whitelist/whitelist.service'; import { @@ -366,6 +367,18 @@ export class JobService { jobEntity.escrowAddress = escrowAddress; await this.jobRepository.updateOne(jobEntity); + const oracleType = this.getOracleType(jobEntity.requestType); + const webhookEntity = new WebhookEntity(); + Object.assign(webhookEntity, { + escrowAddress: jobEntity.escrowAddress, + chainId: jobEntity.chainId, + eventType: EventType.ESCROW_CREATED, + oracleType: oracleType, + hasSignature: oracleType !== OracleType.HCAPTCHA ? true : false, + oracleAddress: jobEntity.exchangeOracle, + }); + await this.webhookRepository.createUnique(webhookEntity); + return jobEntity; } diff --git a/packages/apps/job-launcher/server/src/modules/storage/storage.service.spec.ts b/packages/apps/job-launcher/server/src/modules/storage/storage.service.spec.ts index a41ffabf7e..32f30c88cf 100644 --- a/packages/apps/job-launcher/server/src/modules/storage/storage.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/storage/storage.service.spec.ts @@ -220,6 +220,7 @@ describe('StorageService', () => { 'solution', expect.any(String), expect.any(String), + undefined, { 'Content-Type': ContentType.APPLICATION_JSON, 'Cache-Control': 'no-store', From ddd8372baebb7639dbe7263a2f9175ab30332780 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 18:14:24 +0300 Subject: [PATCH 04/21] chore(deps-dev): bump prettier from 3.6.2 to 3.7.4 (#3711) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/dashboard/client/package.json | 2 +- packages/apps/dashboard/server/package.json | 2 +- packages/apps/faucet/client/package.json | 2 +- .../exchange-oracle/client/package.json | 2 +- .../exchange-oracle/server/package.json | 2 +- .../fortune/recording-oracle/package.json | 2 +- packages/apps/human-app/frontend/package.json | 2 +- packages/apps/human-app/server/package.json | 2 +- .../apps/job-launcher/client/package.json | 2 +- .../apps/job-launcher/server/package.json | 2 +- .../reputation-oracle/server/package.json | 2 +- packages/apps/staking/package.json | 2 +- packages/core/package.json | 2 +- packages/libs/logger/package.json | 2 +- .../human-protocol-sdk/package.json | 2 +- packages/sdk/typescript/subgraph/package.json | 2 +- yarn.lock | 40 +++++++++---------- 17 files changed, 36 insertions(+), 36 deletions(-) diff --git a/packages/apps/dashboard/client/package.json b/packages/apps/dashboard/client/package.json index 1b65d1750d..b733e08e02 100644 --- a/packages/apps/dashboard/client/package.json +++ b/packages/apps/dashboard/client/package.json @@ -59,7 +59,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.11", "globals": "^16.2.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "sass": "^1.89.2", "typescript": "^5.6.3", "typescript-eslint": "^8.33.0", diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index dde650391f..2f12644ba2 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -53,7 +53,7 @@ "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", "jest": "30.2.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", "ts-node": "^10.0.0", diff --git a/packages/apps/faucet/client/package.json b/packages/apps/faucet/client/package.json index 6477ef42cd..bb8469153c 100644 --- a/packages/apps/faucet/client/package.json +++ b/packages/apps/faucet/client/package.json @@ -38,7 +38,7 @@ "eslint-plugin-import": "^2.29.0", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^5.1.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "typescript": "^5.8.3", "vite": "^6.2.4", "vite-plugin-node-polyfills": "^0.23.0" diff --git a/packages/apps/fortune/exchange-oracle/client/package.json b/packages/apps/fortune/exchange-oracle/client/package.json index 86960b89de..79f1eef5e0 100644 --- a/packages/apps/fortune/exchange-oracle/client/package.json +++ b/packages/apps/fortune/exchange-oracle/client/package.json @@ -54,7 +54,7 @@ "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.11", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "typescript": "^5.6.3", "vite": "^6.2.4", "vite-plugin-node-polyfills": "^0.23.0" diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 74e23e701c..6b50cffec5 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -78,7 +78,7 @@ "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", "jest": "30.2.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", "ts-node": "^10.9.2", diff --git a/packages/apps/fortune/recording-oracle/package.json b/packages/apps/fortune/recording-oracle/package.json index fb17499389..9fc5582d36 100644 --- a/packages/apps/fortune/recording-oracle/package.json +++ b/packages/apps/fortune/recording-oracle/package.json @@ -52,7 +52,7 @@ "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", "jest": "^30.2.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "ts-node": "^10.9.2", "typescript": "^5.8.3" } diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index 1894d6f579..715276ac53 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -77,7 +77,7 @@ "husky": "^9.1.6", "jsdom": "^25.0.1", "lint-staged": "^15.4.3", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "typescript": "^5.6.3", "vite": "^6.2.4", "vitest": "^3.1.1" diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index 7a1451a287..cff0252a8f 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -71,7 +71,7 @@ "eslint-plugin-prettier": "^5.2.1", "jest": "30.2.0", "nock": "^13.5.1", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", "ts-node": "^10.9.2", diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 24fc2a1abe..9e54324849 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -76,7 +76,7 @@ "eslint-plugin-import": "^2.29.0", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^5.1.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "resize-observer-polyfill": "^1.5.1", "vite": "^6.2.4", "vite-plugin-node-polyfills": "^0.23.0" diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index 5bf4ee45c4..174d6ada53 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -92,7 +92,7 @@ "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", "jest": "30.2.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", "ts-node": "^10.9.2", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 9a8dcf6733..5997ed8aea 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -93,7 +93,7 @@ "globals": "^16.3.0", "jest": "30.2.0", "nock": "^14.0.3", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "ts-jest": "29.2.5", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", diff --git a/packages/apps/staking/package.json b/packages/apps/staking/package.json index d79cfc6022..fcb358a277 100644 --- a/packages/apps/staking/package.json +++ b/packages/apps/staking/package.json @@ -54,7 +54,7 @@ "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.11", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "sass": "^1.89.2", "typescript": "^5.6.3", "vite": "^6.2.4", diff --git a/packages/core/package.json b/packages/core/package.json index ff7700b083..1314832146 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -80,7 +80,7 @@ "hardhat-dependency-compiler": "^1.2.1", "hardhat-gas-reporter": "^2.0.2", "openpgp": "6.2.2", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "prettier-plugin-solidity": "^1.3.1", "solidity-coverage": "^0.8.16", "tenderly": "^0.9.1", diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json index 7267f84582..f7d38d690f 100644 --- a/packages/libs/logger/package.json +++ b/packages/libs/logger/package.json @@ -28,7 +28,7 @@ "eslint-plugin-import": "^2.32.0", "eslint-plugin-prettier": "^5.5.1", "globals": "^16.3.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "ts-node": "^10.9.2", "typescript": "^5.8.3", "typescript-eslint": "^8.35.1" diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index fed510c51e..67a4a66f3c 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -54,7 +54,7 @@ "eslint": "^9.39.1", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "ts-node": "^10.9.2", "typedoc": "^0.28.7", "typedoc-plugin-markdown": "^4.2.3", diff --git a/packages/sdk/typescript/subgraph/package.json b/packages/sdk/typescript/subgraph/package.json index 8c0616a14a..50e13ffc6b 100644 --- a/packages/sdk/typescript/subgraph/package.json +++ b/packages/sdk/typescript/subgraph/package.json @@ -46,7 +46,7 @@ "graphql": "^16.6.0", "matchstick-as": "^0.6.0", "mustache": "^4.2.0", - "prettier": "^3.4.2" + "prettier": "^3.7.4" }, "lint-staged": { "*.{ts,graphql}": [ diff --git a/yarn.lock b/yarn.lock index 1e635094d0..b8567ac77b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -131,7 +131,7 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.2.0" eslint-plugin-react-refresh: "npm:^0.4.11" globals: "npm:^16.2.0" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-number-format: "npm:^5.4.3" @@ -184,7 +184,7 @@ __metadata: ethers: "npm:~6.15.0" jest: "npm:30.2.0" lodash: "npm:^4.17.21" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" source-map-support: "npm:^0.5.20" @@ -211,7 +211,7 @@ __metadata: eslint-plugin-import: "npm:^2.29.0" eslint-plugin-react: "npm:^7.34.3" eslint-plugin-react-hooks: "npm:^5.1.0" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-loading-skeleton: "npm:^3.3.1" @@ -271,7 +271,7 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.1.0" eslint-plugin-react-refresh: "npm:^0.4.11" ethers: "npm:^6.15.0" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-router-dom: "npm:^6.24.1" @@ -331,7 +331,7 @@ __metadata: passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" pg: "npm:8.13.1" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" source-map-support: "npm:^0.5.20" @@ -373,7 +373,7 @@ __metadata: jest: "npm:^30.2.0" joi: "npm:^17.13.3" minio: "npm:8.0.6" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" ts-node: "npm:^10.9.2" @@ -446,7 +446,7 @@ __metadata: material-react-table: "npm:3.0.1" mui-image: "npm:^1.0.7" notistack: "npm:^3.0.1" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" prop-types: "npm:^15.8.1" query-string: "npm:^9.0.0" react: "npm:^18.3.1" @@ -518,7 +518,7 @@ __metadata: nock: "npm:^13.5.1" passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" source-map-support: "npm:^0.5.20" @@ -567,7 +567,7 @@ __metadata: file-saver: "npm:^2.0.5" formik: "npm:^2.4.2" jwt-decode: "npm:^4.0.0" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-redux: "npm:^9.1.0" @@ -644,7 +644,7 @@ __metadata: passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" pg: "npm:8.13.1" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" source-map-support: "npm:^0.5.20" @@ -719,7 +719,7 @@ __metadata: passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" pg: "npm:8.13.1" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" ts-jest: "npm:29.2.5" @@ -758,7 +758,7 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.1.0" eslint-plugin-react-refresh: "npm:^0.4.11" ethers: "npm:^6.15.0" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" react-router-dom: "npm:^6.24.1" @@ -4914,7 +4914,7 @@ __metadata: hardhat-dependency-compiler: "npm:^1.2.1" hardhat-gas-reporter: "npm:^2.0.2" openpgp: "npm:6.2.2" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" prettier-plugin-solidity: "npm:^1.3.1" solidity-coverage: "npm:^0.8.16" tenderly: "npm:^0.9.1" @@ -4941,7 +4941,7 @@ __metadata: globals: "npm:^16.3.0" pino: "npm:^10.1.0" pino-pretty: "npm:^13.1.2" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" ts-node: "npm:^10.9.2" typescript: "npm:^5.8.3" typescript-eslint: "npm:^8.35.1" @@ -4990,7 +4990,7 @@ __metadata: graphql-request: "npm:^7.3.4" graphql-tag: "npm:^2.12.6" openpgp: "npm:^6.2.2" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" secp256k1: "npm:^5.0.1" ts-node: "npm:^10.9.2" typedoc: "npm:^0.28.7" @@ -10851,7 +10851,7 @@ __metadata: graphql: "npm:^16.6.0" matchstick-as: "npm:^0.6.0" mustache: "npm:^4.2.0" - prettier: "npm:^3.4.2" + prettier: "npm:^3.7.4" languageName: unknown linkType: soft @@ -26012,12 +26012,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.4.2": - version: 3.6.2 - resolution: "prettier@npm:3.6.2" +"prettier@npm:^3.7.4": + version: 3.7.4 + resolution: "prettier@npm:3.7.4" bin: prettier: bin/prettier.cjs - checksum: 10c0/488cb2f2b99ec13da1e50074912870217c11edaddedeadc649b1244c749d15ba94e846423d062e2c4c9ae683e2d65f754de28889ba06e697ac4f988d44f45812 + checksum: 10c0/9675d2cd08eacb1faf1d1a2dbfe24bfab6a912b059fc9defdb380a408893d88213e794a40a2700bd29b140eb3172e0b07c852853f6e22f16f3374659a1a13389 languageName: node linkType: hard From 255be933c90af83844923932cb872489c1ba04b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 18:22:43 +0300 Subject: [PATCH 05/21] chore(deps): bump @fontsource/roboto from 5.2.8 to 5.2.9 (#3709) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/human-app/frontend/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/apps/human-app/frontend/package.json b/packages/apps/human-app/frontend/package.json index 715276ac53..3f28bd9c70 100644 --- a/packages/apps/human-app/frontend/package.json +++ b/packages/apps/human-app/frontend/package.json @@ -20,7 +20,7 @@ "@emotion/styled": "^11.11.0", "@faker-js/faker": "^9.7.0", "@fontsource/inter": "^5.0.17", - "@fontsource/roboto": "^5.2.6", + "@fontsource/roboto": "^5.2.9", "@hcaptcha/react-hcaptcha": "^1.14.0", "@hookform/resolvers": "^5.1.0", "@human-protocol/sdk": "workspace:*", diff --git a/yarn.lock b/yarn.lock index b8567ac77b..a9d4c303c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -406,7 +406,7 @@ __metadata: "@emotion/styled": "npm:^11.11.0" "@faker-js/faker": "npm:^9.7.0" "@fontsource/inter": "npm:^5.0.17" - "@fontsource/roboto": "npm:^5.2.6" + "@fontsource/roboto": "npm:^5.2.9" "@hcaptcha/react-hcaptcha": "npm:^1.14.0" "@hookform/resolvers": "npm:^5.1.0" "@human-protocol/sdk": "workspace:*" @@ -4352,10 +4352,10 @@ __metadata: languageName: node linkType: hard -"@fontsource/roboto@npm:^5.2.6": - version: 5.2.8 - resolution: "@fontsource/roboto@npm:5.2.8" - checksum: 10c0/b215a7e08d65063e9e1714e39c023f0a1f2d33f0d48f06edf4e0d09a8945f682dd39ca7089efb83a48ceffa20d92d65392297831198e9a694b5be8a96b1a40cd +"@fontsource/roboto@npm:^5.2.9": + version: 5.2.9 + resolution: "@fontsource/roboto@npm:5.2.9" + checksum: 10c0/8280ab6504ab7da105c77afc1231236be86f7cd02a708e25b6cfc2871975699a44be7a42491e59934f2a84c874a8109bb2babfbc6b1986bcad9f3ac1de3980ca languageName: node linkType: hard From 2f5266e6c3b1123b823be0837799678a6670f49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Mon, 15 Dec 2025 20:18:27 +0100 Subject: [PATCH 06/21] Remove audino (#3715) --- .../Jobs/Create/AudinoJobRequestForm.tsx | 671 ------------------ .../src/components/Jobs/Create/CreateJob.tsx | 3 - .../components/Jobs/Create/CryptoPayForm.tsx | 9 - .../components/Jobs/Create/FiatPayForm.tsx | 19 +- .../src/components/Jobs/Create/helpers.ts | 36 - .../src/components/Jobs/Create/schema.ts | 25 - .../job-launcher/client/src/services/job.ts | 28 - .../job-launcher/client/src/types/index.ts | 46 -- .../server/src/common/config/env-schema.ts | 2 - .../src/common/config/web3-config.service.ts | 18 - .../server/src/common/enums/job.ts | 7 +- .../server/src/common/enums/webhook.ts | 1 + .../server/src/common/utils/storage.ts | 4 +- .../server/src/modules/job/fixtures.ts | 40 +- .../server/src/modules/job/job.controller.ts | 37 - .../server/src/modules/job/job.dto.ts | 58 -- .../src/modules/job/job.service.spec.ts | 96 --- .../server/src/modules/job/job.service.ts | 30 +- .../server/src/modules/manifest/fixtures.ts | 59 +- .../src/modules/manifest/manifest.dto.ts | 65 +- .../modules/manifest/manifest.service.spec.ts | 72 -- .../src/modules/manifest/manifest.service.ts | 47 +- .../routing-protocol.service.ts | 9 - .../server/src/common/constants/index.ts | 3 - .../server/src/common/enums/manifest.ts | 5 - .../server/src/common/types/job-result.ts | 17 - .../server/src/common/types/manifest.ts | 15 +- .../escrow-completion.service.spec.ts | 10 - .../escrow-completion.service.ts | 12 - .../audino-payouts-calculator.ts | 73 -- .../payouts-calculation/index.ts | 1 - .../payouts-calculation/module.ts | 13 +- .../audino-results-processor.ts | 21 - .../results-processing/index.ts | 1 - .../results-processing/module.ts | 13 +- .../server/src/utils/manifest.ts | 14 +- 36 files changed, 23 insertions(+), 1557 deletions(-) delete mode 100644 packages/apps/job-launcher/client/src/components/Jobs/Create/AudinoJobRequestForm.tsx delete mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/audino-payouts-calculator.ts delete mode 100644 packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/audino-results-processor.ts diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/AudinoJobRequestForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/AudinoJobRequestForm.tsx deleted file mode 100644 index 5d7101a397..0000000000 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/AudinoJobRequestForm.tsx +++ /dev/null @@ -1,671 +0,0 @@ -import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; -import { - Autocomplete, - Box, - Button, - Chip, - FormControl, - FormHelperText, - Grid, - InputAdornment, - InputLabel, - MenuItem, - Select, - TextField, - Tooltip, - Typography, -} from '@mui/material'; -import { useFormik } from 'formik'; -import React, { useEffect, useState } from 'react'; -import { - Accordion, - AccordionDetails, - AccordionSummary, -} from '../../../components/Accordion'; -import { CollectionsFilledIcon } from '../../../components/Icons/CollectionsFilledIcon'; -import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; -import { getQualifications } from '../../../services/qualification'; -import { - AudinoJobType, - AWSRegions, - GCSRegions, - Qualification, - StorageProviders, -} from '../../../types'; -import { mapAudinoFormValues } from './helpers'; -import { AudinoJobRequestValidationSchema } from './schema'; - -export const AudinoJobRequestForm = () => { - const { jobRequest, updateJobRequest, goToPrevStep, goToNextStep } = - useCreateJobPageUI(); - const [expanded, setExpanded] = useState(['panel1']); - const [qualificationsOptions, setQualificationsOptions] = useState< - Qualification[] - >([]); - - const handleChange = - (panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => { - if (newExpanded) { - setExpanded([...expanded, panel]); - } else { - setExpanded(expanded.filter((item) => item !== panel)); - } - }; - - const persistedFormValues = mapAudinoFormValues( - jobRequest, - qualificationsOptions, - ); - - const initialValues = { ...persistedFormValues }; - - useEffect(() => { - const fetchData = async () => { - if (jobRequest.chainId !== undefined) { - try { - setQualificationsOptions(await getQualifications(jobRequest.chainId)); - } catch (error) { - console.error('Error fetching data:', error); - } - } - }; - - fetchData(); - }, [jobRequest.chainId]); - - const handleNext = ({ - type, - labels, - description, - qualifications, - dataProvider, - dataRegion, - dataBucketName, - dataPath, - gtProvider, - gtRegion, - gtBucketName, - gtPath, - userGuide, - accuracyTarget, - segmentDuration, - }: ReturnType) => { - updateJobRequest({ - ...jobRequest, - audinoRequest: { - labels: labels.map((name: string) => ({ name })), - type, - description, - qualifications: (qualifications as Qualification[]).map( - (qualification) => qualification.reference, - ), - data: { - dataset: { - provider: dataProvider, - region: dataRegion, - bucketName: dataBucketName, - path: dataPath, - }, - }, - groundTruth: { - provider: gtProvider, - region: gtRegion, - bucketName: gtBucketName, - path: gtPath, - }, - userGuide, - accuracyTarget, - segmentDuration, - }, - }); - goToNextStep(); - }; - - const { - errors, - touched, - values, - dirty, - isValid, - handleSubmit, - handleBlur, - setFieldValue, - } = useFormik({ - initialValues, - validationSchema: AudinoJobRequestValidationSchema, - onSubmit: handleNext, - validateOnChange: true, - validateOnMount: true, - }); - - const dataRegions = - values.dataProvider === StorageProviders.AWS ? AWSRegions : GCSRegions; - - const gtRegions = - values.gtProvider === StorageProviders.AWS ? AWSRegions : GCSRegions; - - return ( - -
- - - - - General - - - - - - - - Type of job - - - - - - - { - const updatedLabels = (newValues as string[]).map( - (label: string) => - label.startsWith('Add: ') - ? label.replace('Add: ', '') - : label, - ); - setFieldValue('labels', updatedLabels); - }} - filterOptions={(options: any, params) => { - const filtered = options; - const { inputValue } = params; - if (inputValue !== '' && !options.includes(inputValue)) { - filtered.push('Add: ' + inputValue); - } - return filtered; - }} - selectOnFocus - onBlur={handleBlur} - handleHomeEndKeys - renderTags={(value, getTagProps) => - value.map((option, index) => ( - - )) - } - renderInput={(params) => ( - - - - )} - /> - {errors.labels && ( - - {errors.labels} - - )} - - - - - - setFieldValue('description', e.target.value) - } - onBlur={handleBlur} - placeholder="Description" - label="Description" - error={touched.description && Boolean(errors.description)} - helperText={errors.description} - multiline - rows={4} - /> - - - - - - - Qualifications - - - - - - - - - option.title} - value={values.qualifications} - onChange={(event, newValues) => { - setFieldValue('qualifications', newValues); - }} - selectOnFocus - onBlur={handleBlur} - handleHomeEndKeys - renderTags={(value, getTagProps) => - value.map((option, index) => ( - - )) - } - renderInput={(params) => ( - - - - )} - /> - - - - - - - - - - - Job annotation details - - - - - - - - Datasets - - - - - - Storage Provider - - - - - - - - Region - - - {errors.dataRegion && ( - - {errors.dataRegion} - - )} - - - - - - setFieldValue('dataBucketName', e.target.value) - } - error={ - touched.dataBucketName && Boolean(errors.dataBucketName) - } - helperText={errors.dataBucketName} - /> - - - - - - setFieldValue('dataPath', e.target.value) - } - error={touched.dataPath && Boolean(errors.dataPath)} - helperText={errors.dataPath} - InputProps={{ - endAdornment: ( - - - - - - ), - }} - /> - - - - - - - - Ground truth - - - - - - - - - - Storage Provider - - - - - - - - Region - - - {errors.gtRegion && ( - - {errors.gtRegion} - - )} - - - - - - setFieldValue('gtBucketName', e.target.value) - } - error={ - touched.gtBucketName && Boolean(errors.gtBucketName) - } - helperText={errors.gtBucketName} - /> - - - - - setFieldValue('gtPath', e.target.value)} - onBlur={handleBlur} - error={touched.gtPath && Boolean(errors.gtPath)} - InputProps={{ - endAdornment: ( - - - - - - ), - }} - /> - - - - - - - - setFieldValue('userGuide', e.target.value) - } - onBlur={handleBlur} - placeholder="Annotator's guideline for data labeling" - label="User Guide URL" - error={touched.userGuide && Boolean(errors.userGuide)} - helperText={errors.userGuide} - InputProps={{ - endAdornment: ( - - - - - - ), - }} - /> - - - - - - setFieldValue('accuracyTarget', e.target.value) - } - onBlur={handleBlur} - error={ - touched.accuracyTarget && Boolean(errors.accuracyTarget) - } - helperText={errors.accuracyTarget} - InputProps={{ - endAdornment: ( - - - - - - ), - }} - /> - - - - - - - - setFieldValue('segmentDuration', e.target.value) - } - onBlur={handleBlur} - error={ - touched.segmentDuration && - Boolean(errors.segmentDuration) - } - helperText={errors.segmentDuration} - InputProps={{ - endAdornment: ( - - - - - - ), - }} - /> - - - - - - - - - - -
-
- ); -}; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx index 508b617fca..fedc78c4db 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx @@ -6,7 +6,6 @@ import { NetworkSelect } from '../../../components/NetworkSelect'; import { IS_MAINNET } from '../../../constants/chains'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; import { JobType, PayMethod } from '../../../types'; -import { AudinoJobRequestForm } from './AudinoJobRequestForm'; import { CvatJobRequestForm } from './CvatJobRequestForm'; import { FortuneJobRequestForm } from './FortuneJobRequestForm'; import { HCaptchaJobRequestForm } from './HCaptchaJobRequestForm'; @@ -69,7 +68,6 @@ export const CreateJob = () => { {/* {!IS_MAINNET && ( hCaptcha )} */} - Audino { {jobRequest.jobType === JobType.FORTUNE && } {jobRequest.jobType === JobType.CVAT && } {jobRequest.jobType === JobType.HCAPTCHA && } - {jobRequest.jobType === JobType.AUDINO && } ); }; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx index 270ec7d88b..4b8a106d13 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx @@ -224,7 +224,6 @@ export const CryptoPayForm = ({ fortuneRequest, cvatRequest, hCaptchaRequest, - audinoRequest, } = jobRequest; if (jobType === JobType.FORTUNE && fortuneRequest) { await jobService.createFortuneJob( @@ -244,14 +243,6 @@ export const CryptoPayForm = ({ ); } else if (jobType === JobType.HCAPTCHA && hCaptchaRequest) { await jobService.createHCaptchaJob(chainId, hCaptchaRequest); - } else if (jobType === JobType.AUDINO && audinoRequest) { - await jobService.createAudinoJob( - chainId, - audinoRequest, - paymentTokenSymbol, - Number(amount), - fundTokenSymbol, - ); } onFinish(); } catch (err) { diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx index 491c3e3581..d2e2e5e164 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx @@ -29,7 +29,6 @@ import { CURRENCY } from '../../../constants/payment'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; import { useSnackbar } from '../../../providers/SnackProvider'; import { - createAudinoJob, createCvatJob, createFortuneJob, createHCaptchaJob, @@ -248,14 +247,8 @@ export const FiatPayForm = ({ } // create job - const { - jobType, - chainId, - fortuneRequest, - cvatRequest, - hCaptchaRequest, - audinoRequest, - } = jobRequest; + const { jobType, chainId, fortuneRequest, cvatRequest, hCaptchaRequest } = + jobRequest; if (!chainId) return; if (jobType === JobType.FORTUNE && fortuneRequest) { @@ -276,14 +269,6 @@ export const FiatPayForm = ({ ); } else if (jobType === JobType.HCAPTCHA && hCaptchaRequest) { await createHCaptchaJob(chainId, hCaptchaRequest); - } else if (jobType === JobType.AUDINO && audinoRequest) { - await createAudinoJob( - chainId, - audinoRequest, - CURRENCY.usd, - amount, - tokenSymbol, - ); } // Update balance and finish payment diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/helpers.ts b/packages/apps/job-launcher/client/src/components/Jobs/Create/helpers.ts index cbea2eaf54..cd1fe2e2b0 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/helpers.ts +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/helpers.ts @@ -67,39 +67,3 @@ export const mapFortuneFormValues = ( : [], }; }; - -export const mapAudinoFormValues = ( - jobRequest: JobRequest, - qualificationsOptions: Qualification[], -) => { - const { audinoRequest } = jobRequest; - - return { - type: audinoRequest?.type, - labels: audinoRequest?.labels?.map((label) => label.name) || [], - description: audinoRequest?.description || '', - qualifications: audinoRequest?.qualifications - ? qualificationsOptions.filter((q: Qualification) => - audinoRequest?.qualifications?.includes(q.reference), - ) - : [], - - dataProvider: - audinoRequest?.data?.dataset?.provider || StorageProviders.AWS, - dataRegion: - (audinoRequest?.data?.dataset?.region as AWSRegions | GCSRegions) || '', - dataBucketName: audinoRequest?.data?.dataset?.bucketName || '', - dataPath: audinoRequest?.data?.dataset?.path || '', - - gtProvider: audinoRequest?.groundTruth?.provider || StorageProviders.AWS, - gtRegion: - (audinoRequest?.groundTruth?.region as AWSRegions | GCSRegions) || '', - gtBucketName: audinoRequest?.groundTruth?.bucketName || '', - gtPath: audinoRequest?.groundTruth?.path || '', - - userGuide: audinoRequest?.userGuide || '', - accuracyTarget: audinoRequest?.accuracyTarget || 50, - - segmentDuration: audinoRequest?.segmentDuration || 0, - }; -}; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts b/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts index 609cf06ad9..827358218a 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts @@ -89,28 +89,3 @@ export const HCaptchaJobRequesteValidationSchema = Yup.object().shape({ images: Yup.array().of(Yup.string().url('Invalid Image URL')), qualifications: Yup.array().of(Yup.object()), }); - -export const AudinoJobRequestValidationSchema = Yup.object().shape({ - labels: Yup.array().of(Yup.string()).min(1, 'At least one label is required'), - description: Yup.string().required('Description is required'), - dataProvider: Yup.string().required('Provider is required'), - dataRegion: Yup.string().required('Region is required'), - dataBucketName: Yup.string().required('Bucket name is required'), - dataPath: Yup.string().optional(), - gtProvider: Yup.string().required('Provider is required'), - gtRegion: Yup.string().required('Region is required'), - gtBucketName: Yup.string().required('Bucket name is required'), - gtPath: Yup.string().optional(), - userGuide: Yup.string() - .required('User Guide URL is required') - .url('Invalid URL'), - accuracyTarget: Yup.number() - .required('Accuracy target is required') - .moreThan(0, 'Accuracy target must be greater than 0') - .max(100, 'Accuracy target must be less than or equal to 100'), - qualifications: Yup.array().of(Yup.object()), - segmentDuration: Yup.number() - .required('Segment duration is required') - .moreThan(0, 'Segment duration must be greater than 0') - .max(3600000, 'Segment duration must be less than or equal to 3600000'), // one hour in ms -}); diff --git a/packages/apps/job-launcher/client/src/services/job.ts b/packages/apps/job-launcher/client/src/services/job.ts index 39e9ced548..fae6ea60d4 100644 --- a/packages/apps/job-launcher/client/src/services/job.ts +++ b/packages/apps/job-launcher/client/src/services/job.ts @@ -8,8 +8,6 @@ import { JobDetailsResponse, HCaptchaRequest, FortuneFinalResult, - AudinoRequest, - CreateAudinoJobRequest, } from '../types'; import api from '../utils/api'; import { getFilenameFromContentDisposition } from '../utils/string'; @@ -68,32 +66,6 @@ export const createHCaptchaJob = async ( }); }; -export const createAudinoJob = async ( - chainId: number, - data: AudinoRequest, - paymentCurrency: string, - paymentAmount: number | string, - escrowFundToken: string, -) => { - const body: CreateAudinoJobRequest = { - chainId, - requesterDescription: data.description, - paymentCurrency, - paymentAmount: Number(paymentAmount), - escrowFundToken, - data: data.data, - labels: data.labels, - minQuality: Number(data.accuracyTarget) / 100, - groundTruth: data.groundTruth, - userGuide: data.userGuide, - type: data.type, - qualifications: data.qualifications, - segmentDuration: Number(data.segmentDuration), - }; - - await api.post('/job/audino', body); -}; - export const getJobList = async ({ chainId = ChainId.ALL, status, diff --git a/packages/apps/job-launcher/client/src/types/index.ts b/packages/apps/job-launcher/client/src/types/index.ts index a0813f42a0..6add95a163 100644 --- a/packages/apps/job-launcher/client/src/types/index.ts +++ b/packages/apps/job-launcher/client/src/types/index.ts @@ -65,22 +65,6 @@ export type CreateCvatJobRequest = { type: CvatJobType; }; -export type CreateAudinoJobRequest = { - chainId: number; - requesterDescription: string; - qualifications?: string[]; - paymentCurrency: string; - paymentAmount: number; - escrowFundToken: string; - data: AudinoData; - labels: Array<{ name: string }>; - minQuality: number; - groundTruth: AudinoDataSource; - userGuide: string; - type: AudinoJobType; - segmentDuration: number; -}; - export enum CreateJobStep { FundingMethod, CreateJob, @@ -104,7 +88,6 @@ export enum JobType { FORTUNE = 'fortune', CVAT = 'cvat', HCAPTCHA = 'hcaptcha', - AUDINO = 'audino', } export enum CvatJobType { @@ -123,11 +106,6 @@ export enum HCaptchaJobType { COMPARISON = 'comparison', } -export enum AudinoJobType { - AUDIO_TRANSCRIPTION = 'audio_transcription', - AUDIO_ATTRIBUTE_ANNOTATION = 'audio_attribute_annotation', -} - export type FortuneRequest = { title: string; fortunesRequested: number; @@ -269,36 +247,12 @@ export type HCaptchaRequest = { }; }; -type AudinoDataSource = { - provider: StorageProviders; - region: AWSRegions | GCSRegions; - bucketName: string; - path: string; -}; - -type AudinoData = { - dataset: AudinoDataSource; -}; - -export type AudinoRequest = { - labels: Array<{ name: string }>; - type: AudinoJobType; - description: string; - qualifications?: string[]; - data: AudinoData; - groundTruth: AudinoDataSource; - userGuide: string; - accuracyTarget: number; - segmentDuration: number; -}; - export type JobRequest = { jobType: JobType; chainId?: ChainId; fortuneRequest?: FortuneRequest; cvatRequest?: CvatRequest; hCaptchaRequest?: HCaptchaRequest; - audinoRequest?: AudinoRequest; }; export enum JobStatus { diff --git a/packages/apps/job-launcher/server/src/common/config/env-schema.ts b/packages/apps/job-launcher/server/src/common/config/env-schema.ts index 98b5204cb4..2dca07e7b4 100644 --- a/packages/apps/job-launcher/server/src/common/config/env-schema.ts +++ b/packages/apps/job-launcher/server/src/common/config/env-schema.ts @@ -32,8 +32,6 @@ export const envValidator = Joi.object({ REPUTATION_ORACLES: Joi.string().required(), CVAT_EXCHANGE_ORACLE_ADDRESS: Joi.string().required(), CVAT_RECORDING_ORACLE_ADDRESS: Joi.string().required(), - AUDINO_EXCHANGE_ORACLE_ADDRESS: Joi.string(), - AUDINO_RECORDING_ORACLE_ADDRESS: Joi.string(), HCAPTCHA_ORACLE_ADDRESS: Joi.string().required(), HCAPTCHA_RECORDING_ORACLE_URI: Joi.string().required(), HCAPTCHA_REPUTATION_ORACLE_URI: Joi.string().required(), diff --git a/packages/apps/job-launcher/server/src/common/config/web3-config.service.ts b/packages/apps/job-launcher/server/src/common/config/web3-config.service.ts index f5a5ee8742..b2f0f8a5d0 100644 --- a/packages/apps/job-launcher/server/src/common/config/web3-config.service.ts +++ b/packages/apps/job-launcher/server/src/common/config/web3-config.service.ts @@ -93,24 +93,6 @@ export class Web3ConfigService { return this.configService.getOrThrow('HCAPTCHA_ORACLE_ADDRESS'); } - /** - * Address of the Audino exchange oracle. - */ - get audinoExchangeOracleAddress(): string { - return this.configService.getOrThrow( - 'AUDINO_EXCHANGE_ORACLE_ADDRESS', - ); - } - - /** - * Address of the Audino recording oracle. - */ - get audinoRecordingOracleAddress(): string { - return this.configService.getOrThrow( - 'AUDINO_RECORDING_ORACLE_ADDRESS', - ); - } - get approveAmountUsd(): number { return this.configService.get('APPROVE_AMOUNT_USD', 0); } diff --git a/packages/apps/job-launcher/server/src/common/enums/job.ts b/packages/apps/job-launcher/server/src/common/enums/job.ts index bfba218ae5..e2ad6ca78e 100644 --- a/packages/apps/job-launcher/server/src/common/enums/job.ts +++ b/packages/apps/job-launcher/server/src/common/enums/job.ts @@ -42,6 +42,7 @@ export enum CvatJobType { IMAGE_SKELETONS_FROM_BOXES = 'image_skeletons_from_boxes', } +/** @deprecated Audino jobs are no longer supported. */ export enum AudinoJobType { AUDIO_TRANSCRIPTION = 'audio_transcription', AUDIO_ATTRIBUTE_ANNOTATION = 'audio_attribute_annotation', @@ -54,11 +55,7 @@ export const JobType = [ ...Object.values(AudinoJobType), ]; -export type JobRequestType = - | CvatJobType - | FortuneJobType - | AudinoJobType - | HCaptchaJobType; +export type JobRequestType = CvatJobType | FortuneJobType | HCaptchaJobType; export enum JobCaptchaMode { BATCH = 'batch', diff --git a/packages/apps/job-launcher/server/src/common/enums/webhook.ts b/packages/apps/job-launcher/server/src/common/enums/webhook.ts index 10313b8830..2404534aba 100644 --- a/packages/apps/job-launcher/server/src/common/enums/webhook.ts +++ b/packages/apps/job-launcher/server/src/common/enums/webhook.ts @@ -10,6 +10,7 @@ export enum EventType { export enum OracleType { FORTUNE = 'fortune', CVAT = 'cvat', + /** @deprecated Audino jobs are no longer supported. */ AUDINO = 'audino', HCAPTCHA = 'hcaptcha', } diff --git a/packages/apps/job-launcher/server/src/common/utils/storage.ts b/packages/apps/job-launcher/server/src/common/utils/storage.ts index 2bcb9ae72a..ec7100b4ae 100644 --- a/packages/apps/job-launcher/server/src/common/utils/storage.ts +++ b/packages/apps/job-launcher/server/src/common/utils/storage.ts @@ -3,7 +3,7 @@ import axios, { AxiosError } from 'axios'; import { parseString } from 'xml2js'; import { StorageDataDto } from '../../modules/job/job.dto'; import { ErrorBucket } from '../constants/errors'; -import { AudinoJobType, CvatJobType, JobRequestType } from '../enums/job'; +import { CvatJobType, JobRequestType } from '../enums/job'; import { AWSRegions, StorageProviders } from '../enums/storage'; import { ValidationError } from '../errors'; import { @@ -36,8 +36,6 @@ export function generateBucketUrl( CvatJobType.IMAGE_POINTS, CvatJobType.IMAGE_BOXES_FROM_POINTS, CvatJobType.IMAGE_SKELETONS_FROM_BOXES, - AudinoJobType.AUDIO_TRANSCRIPTION, - AudinoJobType.AUDIO_ATTRIBUTE_ANNOTATION, ] as JobRequestType[] ).includes(jobType) && storageData.provider != StorageProviders.AWS && diff --git a/packages/apps/job-launcher/server/src/modules/job/fixtures.ts b/packages/apps/job-launcher/server/src/modules/job/fixtures.ts index 6907066b5a..f95f9fdc70 100644 --- a/packages/apps/job-launcher/server/src/modules/job/fixtures.ts +++ b/packages/apps/job-launcher/server/src/modules/job/fixtures.ts @@ -5,19 +5,13 @@ import { getMockedRegion, } from '../../../test/fixtures/storage'; import { - AudinoJobType, CvatJobType, EscrowFundToken, FortuneJobType, JobCaptchaShapeType, } from '../../common/enums/job'; import { PaymentCurrency } from '../../common/enums/payment'; -import { - JobAudinoDto, - JobCaptchaDto, - JobCvatDto, - JobFortuneDto, -} from './job.dto'; +import { JobCaptchaDto, JobCvatDto, JobFortuneDto } from './job.dto'; import { JobEntity } from './job.entity'; import { JobStatus } from '../../common/enums/job'; @@ -73,38 +67,6 @@ export const createCvatJobDto = (overrides = {}): JobCvatDto => ({ ...overrides, }); -export const createAudinoJobDto = (overrides = {}): JobAudinoDto => ({ - chainId: ChainId.POLYGON_AMOY, - data: { - dataset: { - provider: getMockedProvider(), - region: getMockedRegion(), - bucketName: faker.lorem.word(), - path: faker.system.filePath(), - }, - }, - groundTruth: { - provider: getMockedProvider(), - region: getMockedRegion(), - bucketName: faker.lorem.word(), - path: faker.system.filePath(), - }, - labels: [{ name: faker.lorem.word() }], - segmentDuration: faker.number.int({ min: 10, max: 100 }), - requesterDescription: faker.lorem.sentence(), - userGuide: faker.internet.url(), - qualifications: [faker.lorem.word()], - minQuality: faker.number.int({ min: 1, max: 100 }), - type: AudinoJobType.AUDIO_TRANSCRIPTION, - paymentCurrency: faker.helpers.arrayElement(paymentCurrencies), - paymentAmount: faker.number.int({ min: 1, max: 1000 }), - escrowFundToken: faker.helpers.arrayElement(escrowFundTokens), - exchangeOracle: faker.finance.ethereumAddress(), - recordingOracle: faker.finance.ethereumAddress(), - reputationOracle: faker.finance.ethereumAddress(), - ...overrides, -}); - export const createCaptchaJobDto = (overrides = {}): JobCaptchaDto => ({ chainId: ChainId.POLYGON_AMOY, data: { diff --git a/packages/apps/job-launcher/server/src/modules/job/job.controller.ts b/packages/apps/job-launcher/server/src/modules/job/job.controller.ts index dece39734b..e5c3bb17c8 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.controller.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.controller.ts @@ -31,7 +31,6 @@ import { MutexManagerService } from '../mutex/mutex-manager.service'; import { FortuneFinalResultDto, GetJobsDto, - JobAudinoDto, JobCancelDto, JobCvatDto, JobDetailsDto, @@ -177,42 +176,6 @@ export class JobController { ); } - @ApiOperation({ - summary: 'Create an Audino job', - description: 'Endpoint to create a new Audino job.', - }) - @ApiBody({ type: JobAudinoDto }) - @ApiResponse({ - status: 201, - description: 'ID of the created Audino job.', - type: Number, - }) - @ApiResponse({ - status: 400, - description: 'Bad Request. Invalid input parameters.', - }) - @ApiResponse({ - status: 401, - description: 'Unauthorized. Missing or invalid credentials.', - }) - @ApiResponse({ - status: 409, - description: 'Conflict. Conflict with the current state of the server.', - }) - @Post('/audino') - public async createAudinoJob( - @Body() data: JobAudinoDto, - @Request() req: RequestWithUser, - ): Promise { - return await this.mutexManagerService.runExclusive( - `user${req.user.id}`, - MUTEX_TIMEOUT, - async () => { - return await this.jobService.createJob(req.user, data.type, data); - }, - ); - } - // @ApiOperation({ // summary: 'Create a hCaptcha job', // description: 'Endpoint to create a new hCaptcha job.', diff --git a/packages/apps/job-launcher/server/src/modules/job/job.dto.ts b/packages/apps/job-launcher/server/src/modules/job/job.dto.ts index 3736cbfd79..32a58b0a85 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.dto.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.dto.ts @@ -31,7 +31,6 @@ import { WorkerBrowser, WorkerLanguage, Country, - AudinoJobType, CvatJobType, JobType, } from '../../common/enums/job'; @@ -216,62 +215,6 @@ export class JobCvatDto extends JobDto { public type: CvatJobType; } -class AudinoLabel { - @ApiProperty() - @IsString() - @IsNotEmpty() - public name: string; -} - -class AudinoDataDto { - @ApiProperty() - @IsObject() - @ValidateNested() - @Type(() => StorageDataDto) - public dataset: StorageDataDto; -} - -export class JobAudinoDto extends JobDto { - @ApiProperty({ name: 'requester_description' }) - @IsString() - @IsNotEmpty() - public requesterDescription: string; - - @ApiProperty() - @IsObject() - @ValidateNested() - @Type(() => AudinoDataDto) - public data: AudinoDataDto; - - @ApiProperty({ type: [AudinoLabel] }) - @IsArray() - @ArrayMinSize(1) - public labels: AudinoLabel[]; - - @ApiProperty({ name: 'min_quality' }) - @IsNumber() - @IsPositive() - @Max(1) - public minQuality: number; - - @ApiProperty({ name: 'ground_truth' }) - @IsObject() - public groundTruth: StorageDataDto; - - @ApiProperty({ name: 'user_guide' }) - @IsUrl() - public userGuide: string; - - @ApiProperty({ enum: AudinoJobType }) - @IsEnumCaseInsensitive(AudinoJobType) - public type: AudinoJobType; - - @ApiProperty({ name: 'segment_duration' }) - @IsNumber() - @IsPositive() - public segmentDuration: number; -} - export class JobCancelDto { @ApiProperty() @IsNumberString() @@ -537,5 +480,4 @@ export type CreateJob = | JobQuickLaunchDto | JobFortuneDto | JobCvatDto - | JobAudinoDto | JobCaptchaDto; diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts index fddeddbac0..d9e1daf9c7 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts @@ -18,7 +18,6 @@ import { ServerConfigService } from '../../common/config/server-config.service'; import { ErrorEscrow, ErrorJob } from '../../common/constants/errors'; import { TOKEN_ADDRESSES } from '../../common/constants/tokens'; import { - AudinoJobType, CvatJobType, EscrowFundToken, FortuneJobType, @@ -40,7 +39,6 @@ import { import { div, max, mul } from '../../common/utils/decimal'; import { getTokenDecimals } from '../../common/utils/tokens'; import { - createMockAudinoManifest, createMockCvatManifest, createMockFortuneManifest, createMockHcaptchaManifest, @@ -58,7 +56,6 @@ import { WebhookRepository } from '../webhook/webhook.repository'; import { WhitelistEntity } from '../whitelist/whitelist.entity'; import { WhitelistService } from '../whitelist/whitelist.service'; import { - createAudinoJobDto, createCaptchaJobDto, createCvatJobDto, createFortuneJobDto, @@ -571,92 +568,6 @@ describe('JobService', () => { }); }); - describe('Audino', () => { - it('should create an Audino job', async () => { - const audinoJobDto = createAudinoJobDto(); - const fundTokenDecimals = getTokenDecimals( - audinoJobDto.chainId!, - audinoJobDto.escrowFundToken, - ); - - const mockManifest = createMockAudinoManifest(); - mockManifestService.createManifest.mockResolvedValueOnce(mockManifest); - const mockUrl = faker.internet.url(); - const mockHash = faker.string.uuid(); - mockManifestService.uploadManifest.mockResolvedValueOnce({ - url: mockUrl, - hash: mockHash, - }); - const jobEntityMock = createJobEntity(); - mockJobRepository.createUnique = jest - .fn() - .mockResolvedValueOnce(jobEntityMock); - mockRateService.getRate - .mockResolvedValueOnce(tokenToUsdRate) - .mockResolvedValueOnce(usdToTokenRate); - - await jobService.createJob( - userMock, - AudinoJobType.AUDIO_TRANSCRIPTION, - audinoJobDto, - ); - - expect(mockWeb3Service.validateChainId).toHaveBeenCalledWith( - audinoJobDto.chainId, - ); - expect(mockRoutingProtocolService.selectOracles).not.toHaveBeenCalled(); - expect(mockRoutingProtocolService.validateOracles).toHaveBeenCalledWith( - audinoJobDto.chainId, - audinoJobDto.type, - audinoJobDto.reputationOracle, - audinoJobDto.exchangeOracle, - audinoJobDto.recordingOracle, - ); - expect(mockManifestService.createManifest).toHaveBeenCalledWith( - audinoJobDto, - audinoJobDto.type, - audinoJobDto.paymentAmount, - fundTokenDecimals, - ); - expect(mockManifestService.uploadManifest).toHaveBeenCalledWith( - audinoJobDto.chainId, - mockManifest, - [ - audinoJobDto.exchangeOracle, - audinoJobDto.reputationOracle, - audinoJobDto.recordingOracle, - ], - ); - expect(mockPaymentService.createWithdrawalPayment).toHaveBeenCalledWith( - userMock.id, - expect.any(Number), - audinoJobDto.paymentCurrency, - tokenToUsdRate, - ); - expect(mockJobRepository.updateOne).toHaveBeenCalledWith({ - chainId: audinoJobDto.chainId, - userId: userMock.id, - manifestUrl: mockUrl, - manifestHash: mockHash, - requestType: audinoJobDto.type, - fee: expect.any(Number), - fundAmount: Number( - mul( - mul(audinoJobDto.paymentAmount, tokenToUsdRate), - usdToTokenRate, - ).toFixed(6), - ), - status: JobStatus.MODERATION_PASSED, - waitUntil: expect.any(Date), - token: audinoJobDto.escrowFundToken, - exchangeOracle: audinoJobDto.exchangeOracle, - recordingOracle: audinoJobDto.recordingOracle, - reputationOracle: audinoJobDto.reputationOracle, - payments: expect.any(Array), - }); - }); - }); - describe('HCaptcha', () => { it('should create an HCaptcha job', async () => { const captchaJobDto = createCaptchaJobDto(); @@ -1333,13 +1244,6 @@ describe('JobService', () => { }, ); - it.each(Object.values(AudinoJobType))( - 'should return OracleType.AUDINO for Audino job type %s', - (jobType) => { - expect(jobService.getOracleType(jobType)).toBe(OracleType.AUDINO); - }, - ); - it.each(Object.values(HCaptchaJobType))( 'should return OracleType.HCAPTCHA for HCaptcha job type %s', (jobType) => { diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index 9f970ae77b..d1b69abb00 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -1,3 +1,4 @@ +import { Escrow, Escrow__factory } from '@human-protocol/core/typechain-types'; import { ChainId, EscrowClient, @@ -26,7 +27,6 @@ import { import { TOKEN_ADDRESSES } from '../../common/constants/tokens'; import { CronJobType } from '../../common/enums/cron-job'; import { - AudinoJobType, CvatJobType, EscrowFundToken, FortuneJobType, @@ -53,7 +53,6 @@ import { getTokenDecimals } from '../../common/utils/tokens'; import logger from '../../logger'; import { CronJobRepository } from '../cron-job/cron-job.repository'; import { - AudinoManifestDto, CvatManifestDto, FortuneManifestDto, HCaptchaManifestDto, @@ -80,7 +79,6 @@ import { } from './job.dto'; import { JobEntity } from './job.entity'; import { JobRepository } from './job.repository'; -import { Escrow, Escrow__factory } from '@human-protocol/core/typechain-types'; @Injectable() export class JobService { @@ -290,12 +288,7 @@ export class JobService { if ( user.whitelist || ( - [ - AudinoJobType.AUDIO_TRANSCRIPTION, - AudinoJobType.AUDIO_ATTRIBUTE_ANNOTATION, - FortuneJobType.FORTUNE, - HCaptchaJobType.HCAPTCHA, - ] as JobRequestType[] + [FortuneJobType.FORTUNE, HCaptchaJobType.HCAPTCHA] as JobRequestType[] ).includes(requestType) ) { jobEntity.status = JobStatus.MODERATION_PASSED; @@ -593,10 +586,6 @@ export class JobService { return OracleType.FORTUNE; } else if (requestType === HCaptchaJobType.HCAPTCHA) { return OracleType.HCAPTCHA; - } else if ( - Object.values(AudinoJobType).includes(requestType as AudinoJobType) - ) { - return OracleType.AUDINO; } else if ( Object.values(CvatJobType).includes(requestType as CvatJobType) ) { @@ -743,21 +732,6 @@ export class JobService { qualifications: manifest.qualifications, }), }; - } else if ( - Object.values(AudinoJobType).includes( - jobEntity.requestType as AudinoJobType, - ) - ) { - const manifest = manifestData as AudinoManifestDto; - specificManifestDetails = { - requestType: manifest.annotation?.type, - submissionsRequired: manifest.annotation?.segment_duration, - description: manifest.annotation?.description, - ...(manifest.annotation?.qualifications && - manifest.annotation?.qualifications?.length > 0 && { - qualifications: manifest.annotation?.qualifications, - }), - }; } else { const manifest = manifestData as CvatManifestDto; specificManifestDetails = { diff --git a/packages/apps/job-launcher/server/src/modules/manifest/fixtures.ts b/packages/apps/job-launcher/server/src/modules/manifest/fixtures.ts index 9b405e0c48..dde47c00b4 100644 --- a/packages/apps/job-launcher/server/src/modules/manifest/fixtures.ts +++ b/packages/apps/job-launcher/server/src/modules/manifest/fixtures.ts @@ -4,20 +4,18 @@ import { AuthConfigService } from '../../common/config/auth-config.service'; import { CvatConfigService } from '../../common/config/cvat-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { - AudinoJobType, CvatJobType, EscrowFundToken, JobCaptchaRequestType, JobCaptchaShapeType, } from '../../common/enums/job'; import { PaymentCurrency } from '../../common/enums/payment'; -import { JobAudinoDto, JobCaptchaDto, JobCvatDto } from '../job/job.dto'; +import { JobCaptchaDto, JobCvatDto } from '../job/job.dto'; import { getMockedProvider, getMockedRegion, } from '../../../test/fixtures/storage'; import { - AudinoManifestDto, CvatManifestDto, FortuneManifestDto, HCaptchaManifestDto, @@ -77,38 +75,6 @@ export function createJobCvatDto( }; } -export function createJobAudinoDto( - overrides: Partial = {}, -): JobAudinoDto { - return { - data: { - dataset: { - provider: getMockedProvider(), - region: getMockedRegion(), - bucketName: faker.lorem.word(), - path: faker.system.filePath(), - }, - }, - groundTruth: { - provider: getMockedProvider(), - region: getMockedRegion(), - bucketName: faker.lorem.word(), - path: faker.system.filePath(), - }, - labels: [{ name: faker.lorem.word() }], - segmentDuration: faker.number.int({ min: 10, max: 3600000 }), - requesterDescription: faker.lorem.sentence(), - userGuide: faker.internet.url(), - qualifications: [faker.lorem.word()], - minQuality: faker.number.int({ min: 1, max: 100 }), - type: AudinoJobType.AUDIO_TRANSCRIPTION, - paymentCurrency: faker.helpers.arrayElement(Object.values(PaymentCurrency)), - paymentAmount: faker.number.int({ min: 1, max: 1000 }), - escrowFundToken: faker.helpers.arrayElement(Object.values(EscrowFundToken)), - ...overrides, - }; -} - export function createJobCaptchaDto( overrides: Partial = {}, ): JobCaptchaDto { @@ -185,29 +151,6 @@ export function createMockCvatManifest( }; } -export function createMockAudinoManifest( - overrides: Partial = {}, -): AudinoManifestDto { - return { - data: { - data_url: faker.internet.url(), - }, - annotation: { - labels: [{ name: faker.lorem.word() }], - description: faker.lorem.sentence(), - user_guide: faker.internet.url(), - type: AudinoJobType.AUDIO_TRANSCRIPTION, - segment_duration: faker.number.int({ min: 10, max: 360000 }), - qualifications: [faker.lorem.word()], - }, - validation: { - min_quality: faker.number.float({ min: 0.1, max: 1 }), - gt_url: faker.internet.url(), - }, - ...overrides, - }; -} - export function createMockHcaptchaManifest( overrides: Partial = {}, ): HCaptchaManifestDto { diff --git a/packages/apps/job-launcher/server/src/modules/manifest/manifest.dto.ts b/packages/apps/job-launcher/server/src/modules/manifest/manifest.dto.ts index 737c9995b9..bfdd368bd2 100644 --- a/packages/apps/job-launcher/server/src/modules/manifest/manifest.dto.ts +++ b/packages/apps/job-launcher/server/src/modules/manifest/manifest.dto.ts @@ -18,11 +18,7 @@ import { JobCaptchaShapeType, JobRequestType, } from '../../common/enums/job'; -import { - FortuneJobType, - CvatJobType, - AudinoJobType, -} from '../../common/enums/job'; +import { FortuneJobType, CvatJobType } from '../../common/enums/job'; import { Type } from 'class-transformer'; export class FortuneManifestDto { @@ -143,62 +139,6 @@ export class CvatManifestDto { public job_bounty: string; } -class AudinoData { - @IsUrl() - public data_url: string; -} - -class AudinoAnnotation { - @IsArray() - public labels: Array<{ name: string }>; - - @IsString() - public description: string; - - @IsString() - @IsUrl() - public user_guide: string; - - @IsEnumCaseInsensitive(AudinoJobType) - public type: AudinoJobType; - - @IsNumber() - @IsPositive() - public segment_duration: number; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - public qualifications?: string[]; -} - -class AudinoValidation { - @IsNumber() - @IsPositive() - public min_quality: number; - - @IsString() - @IsUrl() - public gt_url: string; -} - -export class AudinoManifestDto { - @IsObject() - @ValidateNested() - @Type(() => AudinoData) - public data: AudinoData; - - @IsObject() - @ValidateNested() - @Type(() => AudinoAnnotation) - public annotation: AudinoAnnotation; - - @IsObject() - @ValidateNested() - @Type(() => AudinoValidation) - public validation: AudinoValidation; -} - export class RestrictedAudience { @IsObject() @IsOptional() @@ -458,5 +398,4 @@ export class ManifestDetails { export type ManifestDto = | FortuneManifestDto | CvatManifestDto - | HCaptchaManifestDto - | AudinoManifestDto; + | HCaptchaManifestDto; diff --git a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.spec.ts b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.spec.ts index 5f28c6fb82..e06ba03ca1 100644 --- a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.spec.ts @@ -27,7 +27,6 @@ import { } from '../../common/constants'; import { ErrorJob } from '../../common/constants/errors'; import { - AudinoJobType, CvatJobType, FortuneJobType, HCaptchaJobType, @@ -47,7 +46,6 @@ import { import { StorageService } from '../storage/storage.service'; import { Web3Service } from '../web3/web3.service'; import { - createJobAudinoDto, createJobCaptchaDto, createJobCvatDto, mockAuthConfigService, @@ -300,76 +298,6 @@ describe('ManifestService', () => { }); }); - describe('createAudinoManifest', () => { - it('should create an Audino manifest for audio transcription successfully', async () => { - const mockDto = createJobAudinoDto(); - const mockRequestType = AudinoJobType.AUDIO_TRANSCRIPTION; - const mockTokenFundAmount = faker.number.int({ min: 1, max: 1000 }); - const mockTokenFundDecimals = faker.number.int({ min: 1, max: 18 }); - - const result = await manifestService.createManifest( - mockDto as any, - mockRequestType, - mockTokenFundAmount, - mockTokenFundDecimals, - ); - - expect(result).toEqual({ - annotation: { - description: mockDto.requesterDescription, - labels: mockDto.labels, - qualifications: mockDto.qualifications || [], - type: mockRequestType, - user_guide: mockDto.userGuide, - segment_duration: mockDto.segmentDuration, - }, - data: { - data_url: generateBucketUrl(mockDto.data.dataset, mockRequestType) - .href, - }, - validation: { - gt_url: generateBucketUrl(mockDto.groundTruth, mockRequestType) - .href, - min_quality: mockDto.minQuality, - }, - }); - }); - - it('should create an Audino manifest for audio attribute annotation successfully', async () => { - const mockDto = createJobAudinoDto(); - const mockRequestType = AudinoJobType.AUDIO_ATTRIBUTE_ANNOTATION; - const mockTokenFundAmount = faker.number.int({ min: 1, max: 1000 }); - const mockTokenFundDecimals = faker.number.int({ min: 1, max: 18 }); - - const result = await manifestService.createManifest( - mockDto as any, - mockRequestType, - mockTokenFundAmount, - mockTokenFundDecimals, - ); - - expect(result).toEqual({ - annotation: { - description: mockDto.requesterDescription, - labels: mockDto.labels, - qualifications: mockDto.qualifications || [], - type: mockRequestType, - user_guide: mockDto.userGuide, - segment_duration: mockDto.segmentDuration, - }, - data: { - data_url: generateBucketUrl(mockDto.data.dataset, mockRequestType) - .href, - }, - validation: { - gt_url: generateBucketUrl(mockDto.groundTruth, mockRequestType) - .href, - min_quality: mockDto.minQuality, - }, - }); - }); - }); - describe('createHCaptchaManifest', () => { const requestType = HCaptchaJobType.HCAPTCHA; const tokenFundAmount = faker.number.int({ min: 1, max: 1000 }); diff --git a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts index 5399c0be61..6276568d13 100644 --- a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts +++ b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts @@ -27,7 +27,6 @@ import { } from '../../common/constants'; import { ErrorJob } from '../../common/constants/errors'; import { - AudinoJobType, CvatJobType, FortuneJobType, HCaptchaJobType, @@ -43,7 +42,6 @@ import { } from '../../common/utils/storage'; import { CreateJob, - JobAudinoDto, JobCaptchaAdvancedDto, JobCaptchaDto, JobCvatDto, @@ -57,7 +55,6 @@ import { import { StorageService } from '../storage/storage.service'; import { Web3Service } from '../web3/web3.service'; import { - AudinoManifestDto, CvatManifestDto, FortuneManifestDto, HCaptchaManifestDto, @@ -108,10 +105,6 @@ export class ManifestService { decimals, ); - case AudinoJobType.AUDIO_TRANSCRIPTION: - case AudinoJobType.AUDIO_ATTRIBUTE_ANNOTATION: - return this.createAudinoManifest(dto as JobAudinoDto, requestType); - default: throw new ValidationError(ErrorJob.InvalidRequestType); } @@ -318,29 +311,6 @@ export class ManifestService { }; } - private async createAudinoManifest( - dto: JobAudinoDto, - requestType: AudinoJobType, - ): Promise { - return { - annotation: { - description: dto.requesterDescription, - labels: dto.labels, - qualifications: dto.qualifications || [], - type: requestType, - user_guide: dto.userGuide, - segment_duration: dto.segmentDuration, - }, - data: { - data_url: generateBucketUrl(dto.data.dataset, requestType).href, - }, - validation: { - gt_url: generateBucketUrl(dto.groundTruth, requestType).href, - min_quality: dto.minQuality, - }, - }; - } - private async createHCaptchaManifest( jobDto: JobCaptchaDto, ): Promise { @@ -590,11 +560,7 @@ export class ManifestService { private async validateManifest( requestType: JobRequestType, - manifest: - | FortuneManifestDto - | CvatManifestDto - | HCaptchaManifestDto - | AudinoManifestDto, + manifest: FortuneManifestDto | CvatManifestDto | HCaptchaManifestDto, ): Promise { let dtoCheck; @@ -603,10 +569,6 @@ export class ManifestService { } else if (requestType === HCaptchaJobType.HCAPTCHA) { return; dtoCheck = new HCaptchaManifestDto(); - } else if ( - Object.values(AudinoJobType).includes(requestType as AudinoJobType) - ) { - dtoCheck = new AudinoManifestDto(); } else { dtoCheck = new CvatManifestDto(); } @@ -622,12 +584,7 @@ export class ManifestService { async downloadManifest( manifestUrl: string, requestType: JobRequestType, - ): Promise< - | FortuneManifestDto - | CvatManifestDto - | HCaptchaManifestDto - | AudinoManifestDto - > { + ): Promise { const manifest = (await this.storageService.downloadJsonLikeData( manifestUrl, )) as ManifestDto; diff --git a/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts b/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts index 2a3827a966..b08e1f6819 100644 --- a/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts +++ b/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts @@ -4,7 +4,6 @@ import { NetworkConfigService } from '../../common/config/network-config.service import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ErrorRoutingProtocol } from '../../common/constants/errors'; import { - AudinoJobType, CvatJobType, HCaptchaJobType, JobRequestType, @@ -176,14 +175,6 @@ export class RoutingProtocolService { exchangeOracle: this.web3ConfigService.cvatExchangeOracleAddress, recordingOracle: this.web3ConfigService.cvatRecordingOracleAddress, }; - } else if ( - Object.values(AudinoJobType).includes(jobType as AudinoJobType) - ) { - return { - reputationOracle: this.web3ConfigService.reputationOracleAddress, - exchangeOracle: this.web3ConfigService.audinoExchangeOracleAddress, - recordingOracle: this.web3ConfigService.audinoRecordingOracleAddress, - }; } const reputationOracle = this.selectReputationOracle(); diff --git a/packages/apps/reputation-oracle/server/src/common/constants/index.ts b/packages/apps/reputation-oracle/server/src/common/constants/index.ts index 637d783de0..1bacfb11fd 100644 --- a/packages/apps/reputation-oracle/server/src/common/constants/index.ts +++ b/packages/apps/reputation-oracle/server/src/common/constants/index.ts @@ -5,9 +5,6 @@ export const JWT_STRATEGY_NAME = 'jwt-http'; export const CVAT_RESULTS_ANNOTATIONS_FILENAME = 'resulting_annotations.zip'; export const CVAT_VALIDATION_META_FILENAME = 'validation_meta.json'; -export const AUDINO_RESULTS_ANNOTATIONS_FILENAME = 'resulting_annotations.zip'; -export const AUDINO_VALIDATION_META_FILENAME = 'validation_meta.json'; - export const HEADER_SIGNATURE_KEY = 'human-signature'; export const RESEND_EMAIL_VERIFICATION_PATH = diff --git a/packages/apps/reputation-oracle/server/src/common/enums/manifest.ts b/packages/apps/reputation-oracle/server/src/common/enums/manifest.ts index 1db8e25a25..80d3c77ade 100644 --- a/packages/apps/reputation-oracle/server/src/common/enums/manifest.ts +++ b/packages/apps/reputation-oracle/server/src/common/enums/manifest.ts @@ -9,8 +9,3 @@ export enum CvatJobType { IMAGE_SKELETONS_FROM_BOXES = 'image_skeletons_from_boxes', IMAGE_POLYGONS = 'image_polygons', } - -export enum AudinoJobType { - AUDIO_TRANSCRIPTION = 'audio_transcription', - AUDIO_ATTRIBUTE_ANNOTATION = 'audio_attribute_annotation', -} diff --git a/packages/apps/reputation-oracle/server/src/common/types/job-result.ts b/packages/apps/reputation-oracle/server/src/common/types/job-result.ts index 2d9338ce89..eb0ff27812 100644 --- a/packages/apps/reputation-oracle/server/src/common/types/job-result.ts +++ b/packages/apps/reputation-oracle/server/src/common/types/job-result.ts @@ -20,20 +20,3 @@ export type CvatAnnotationMeta = { jobs: CvatAnnotationMetaJob[]; results: CvatAnnotationMetaResult[]; }; - -type AudinoAnnotationMetaJob = { - job_id: number; - final_result_id: number; -}; - -export type AudinoAnnotationMetaResult = { - id: number; - job_id: number; - annotator_wallet_address: string; - annotation_quality: number; -}; - -export type AudinoAnnotationMeta = { - jobs: AudinoAnnotationMetaJob[]; - results: AudinoAnnotationMetaResult[]; -}; diff --git a/packages/apps/reputation-oracle/server/src/common/types/manifest.ts b/packages/apps/reputation-oracle/server/src/common/types/manifest.ts index 4685d64d16..774833067e 100644 --- a/packages/apps/reputation-oracle/server/src/common/types/manifest.ts +++ b/packages/apps/reputation-oracle/server/src/common/types/manifest.ts @@ -1,4 +1,4 @@ -import { AudinoJobType, CvatJobType, FortuneJobType } from '@/common/enums'; +import { CvatJobType, FortuneJobType } from '@/common/enums'; export type FortuneManifest = { submissionsRequired: number; @@ -16,15 +16,6 @@ export type CvatManifest = { job_bounty: string; }; -export type AudinoManifest = { - annotation: { - type: AudinoJobType; - }; - validation: { - min_quality: number; - }; -}; - -export type JobManifest = FortuneManifest | CvatManifest | AudinoManifest; +export type JobManifest = FortuneManifest | CvatManifest; -export type JobRequestType = FortuneJobType | CvatJobType | AudinoJobType; +export type JobRequestType = FortuneJobType | CvatJobType; diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts index ff12d9727c..e13aa05392 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts @@ -44,12 +44,10 @@ import { generateEscrowPayoutsBatch, } from './fixtures/escrow-completion'; import { - AudinoPayoutsCalculator, CvatPayoutsCalculator, FortunePayoutsCalculator, } from './payouts-calculation'; import { - AudinoResultsProcessor, CvatResultsProcessor, FortuneResultsProcessor, } from './results-processing'; @@ -125,14 +123,6 @@ describe('EscrowCompletionService', () => { provide: CvatPayoutsCalculator, useValue: mockCvatPayoutsCalculator, }, - { - provide: AudinoResultsProcessor, - useValue: createMock(), - }, - { - provide: AudinoPayoutsCalculator, - useValue: createMock(), - }, ], }).compile(); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts index dd3ea9f65e..205e915fcc 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts @@ -36,14 +36,12 @@ import { EscrowCompletionRepository } from './escrow-completion.repository'; import { EscrowPayoutsBatchEntity } from './escrow-payouts-batch.entity'; import { EscrowPayoutsBatchRepository } from './escrow-payouts-batch.repository'; import { - AudinoPayoutsCalculator, CvatPayoutsCalculator, FortunePayoutsCalculator, EscrowPayoutsCalculator, CalculatedPayout, } from './payouts-calculation'; import { - AudinoResultsProcessor, CvatResultsProcessor, EscrowResultsProcessor, FortuneResultsProcessor, @@ -63,10 +61,8 @@ export class EscrowCompletionService { private readonly storageService: StorageService, private readonly outgoingWebhookService: OutgoingWebhookService, private readonly reputationService: ReputationService, - private readonly audinoResultsProcessor: AudinoResultsProcessor, private readonly cvatResultsProcessor: CvatResultsProcessor, private readonly fortuneResultsProcessor: FortuneResultsProcessor, - private readonly audinoPayoutsCalculator: AudinoPayoutsCalculator, private readonly cvatPayoutsCalculator: CvatPayoutsCalculator, private readonly fortunePayoutsCalculator: FortunePayoutsCalculator, ) {} @@ -481,10 +477,6 @@ export class EscrowCompletionService { return this.cvatResultsProcessor; } - if (manifestUtils.isAudinoJobType(jobRequestType)) { - return this.audinoResultsProcessor; - } - throw new Error( `No escrow results processor defined for '${jobRequestType}' jobs`, ); @@ -501,10 +493,6 @@ export class EscrowCompletionService { return this.cvatPayoutsCalculator; } - if (manifestUtils.isAudinoJobType(jobRequestType)) { - return this.audinoPayoutsCalculator; - } - throw new Error( `No escrow payouts calculator defined for '${jobRequestType}' jobs`, ); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/audino-payouts-calculator.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/audino-payouts-calculator.ts deleted file mode 100644 index c49adbb412..0000000000 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/audino-payouts-calculator.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { EscrowClient } from '@human-protocol/sdk'; -import { Injectable } from '@nestjs/common'; -import type { OverrideProperties } from 'type-fest'; - -import { AUDINO_VALIDATION_META_FILENAME } from '@/common/constants'; -import { AudinoAnnotationMeta, AudinoManifest } from '@/common/types'; -import { StorageService } from '@/modules/storage'; -import { Web3Service } from '@/modules/web3'; - -import { - CalclulatePayoutsInput, - CalculatedPayout, - EscrowPayoutsCalculator, -} from './types'; - -type CalculateAudinoPayoutsInput = OverrideProperties< - CalclulatePayoutsInput, - { manifest: AudinoManifest } ->; - -@Injectable() -export class AudinoPayoutsCalculator implements EscrowPayoutsCalculator { - constructor( - private readonly storageService: StorageService, - private readonly web3Service: Web3Service, - ) {} - - async calculate({ - chainId, - escrowAddress, - }: CalculateAudinoPayoutsInput): Promise { - const signer = this.web3Service.getSigner(chainId); - const escrowClient = await EscrowClient.build(signer); - - const intermediateResultsUrl = - await escrowClient.getIntermediateResultsUrl(escrowAddress); - - const annotations = - await this.storageService.downloadJsonLikeData( - `${intermediateResultsUrl}/${AUDINO_VALIDATION_META_FILENAME}`, - ); - - if (annotations.jobs.length === 0 || annotations.results.length === 0) { - throw new Error('Invalid annotation meta'); - } - const reservedFunds = await escrowClient.getReservedFunds(escrowAddress); - const jobBountyValue = reservedFunds / BigInt(annotations.jobs.length); - - const workersBounties = new Map(); - for (const job of annotations.jobs) { - const jobFinalResult = annotations.results.find( - (result) => result.id === job.final_result_id, - ); - if (jobFinalResult) { - const workerAddress = jobFinalResult.annotator_wallet_address; - - const currentWorkerBounty = workersBounties.get(workerAddress) || 0n; - - workersBounties.set( - workerAddress, - currentWorkerBounty + jobBountyValue, - ); - } - } - - return Array.from(workersBounties.entries()).map( - ([workerAddress, bountyAmount]) => ({ - address: workerAddress, - amount: bountyAmount, - }), - ); - } -} diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/index.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/index.ts index 868e920212..4d386af245 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/index.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/index.ts @@ -1,4 +1,3 @@ -export { AudinoPayoutsCalculator } from './audino-payouts-calculator'; export { CvatPayoutsCalculator } from './cvat-payouts-calculator'; export { FortunePayoutsCalculator } from './fortune-payouts-calculator'; export * from './types'; diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/module.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/module.ts index d60196f22c..578dcd8277 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/module.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/payouts-calculation/module.ts @@ -3,21 +3,12 @@ import { Module } from '@nestjs/common'; import { StorageModule } from '@/modules/storage'; import { Web3Module } from '@/modules/web3'; -import { AudinoPayoutsCalculator } from './audino-payouts-calculator'; import { CvatPayoutsCalculator } from './cvat-payouts-calculator'; import { FortunePayoutsCalculator } from './fortune-payouts-calculator'; @Module({ imports: [StorageModule, Web3Module], - providers: [ - AudinoPayoutsCalculator, - CvatPayoutsCalculator, - FortunePayoutsCalculator, - ], - exports: [ - AudinoPayoutsCalculator, - CvatPayoutsCalculator, - FortunePayoutsCalculator, - ], + providers: [CvatPayoutsCalculator, FortunePayoutsCalculator], + exports: [CvatPayoutsCalculator, FortunePayoutsCalculator], }) export class EscrowPayoutsCalculationModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/audino-results-processor.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/audino-results-processor.ts deleted file mode 100644 index 8c6b8a8c61..0000000000 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/audino-results-processor.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { AUDINO_RESULTS_ANNOTATIONS_FILENAME } from '@/common/constants'; -import { AudinoManifest } from '@/common/types'; - -import { BaseEscrowResultsProcessor } from './escrow-results-processor'; - -@Injectable() -export class AudinoResultsProcessor extends BaseEscrowResultsProcessor { - constructIntermediateResultsUrl(baseUrl: string): string { - return `${baseUrl}/${AUDINO_RESULTS_ANNOTATIONS_FILENAME}`; - } - - async assertResultsComplete(): Promise { - return; - } - - getFinalResultsFileName(hash: string): string { - return `${hash}.zip`; - } -} diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/index.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/index.ts index 3c8da7e4c1..3f4731aceb 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/index.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/index.ts @@ -1,4 +1,3 @@ -export { AudinoResultsProcessor } from './audino-results-processor'; export { CvatResultsProcessor } from './cvat-results-processor'; export { type EscrowResultsProcessor } from './escrow-results-processor'; export { FortuneResultsProcessor } from './fortune-results-processor'; diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/module.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/module.ts index 4149ac6a5a..6057b7d620 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/module.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/module.ts @@ -4,21 +4,12 @@ import { EncryptionModule } from '@/modules/encryption'; import { StorageModule } from '@/modules/storage'; import { Web3Module } from '@/modules/web3'; -import { AudinoResultsProcessor } from './audino-results-processor'; import { CvatResultsProcessor } from './cvat-results-processor'; import { FortuneResultsProcessor } from './fortune-results-processor'; @Module({ imports: [EncryptionModule, StorageModule, Web3Module], - providers: [ - AudinoResultsProcessor, - CvatResultsProcessor, - FortuneResultsProcessor, - ], - exports: [ - AudinoResultsProcessor, - CvatResultsProcessor, - FortuneResultsProcessor, - ], + providers: [CvatResultsProcessor, FortuneResultsProcessor], + exports: [CvatResultsProcessor, FortuneResultsProcessor], }) export class EscrowResultsProcessingModule {} diff --git a/packages/apps/reputation-oracle/server/src/utils/manifest.ts b/packages/apps/reputation-oracle/server/src/utils/manifest.ts index a8fdea9e6a..84804b1901 100644 --- a/packages/apps/reputation-oracle/server/src/utils/manifest.ts +++ b/packages/apps/reputation-oracle/server/src/utils/manifest.ts @@ -1,4 +1,4 @@ -import { AudinoJobType, CvatJobType, FortuneJobType } from '@/common/enums'; +import { CvatJobType, FortuneJobType } from '@/common/enums'; import { JobManifest, JobRequestType } from '@/common/types'; const fortuneJobTypes = Object.values(FortuneJobType); @@ -13,17 +13,7 @@ export function isCvatJobType(value: string): value is CvatJobType { return cvatJobTypes.includes(value as CvatJobType); } -const audinoJobTypes = Object.values(AudinoJobType); - -export function isAudinoJobType(value: string): value is AudinoJobType { - return audinoJobTypes.includes(value as AudinoJobType); -} - -const validJobRequestTypes: string[] = [ - ...fortuneJobTypes, - ...cvatJobTypes, - ...audinoJobTypes, -]; +const validJobRequestTypes: string[] = [...fortuneJobTypes, ...cvatJobTypes]; function assertValidJobRequestType( value: string, From 793af3a6b00b3ce28af76d54714b9baa79905c4f Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Tue, 16 Dec 2025 16:35:21 +0300 Subject: [PATCH 07/21] fix: actions trigger (#3719) --- .github/dependabot.yml | 7 + .../workflows/cd-cvat-exchange-oracle.yaml | 1 - .../workflows/cd-cvat-recording-oracle.yaml | 1 - .github/workflows/cd-job-launcher-server.yaml | 1 - .github/workflows/cd-packages.yaml | 1 - .github/workflows/cd-python-sdk.yaml | 1 - .github/workflows/cd-reputation-oracle.yaml | 1 - .../ci-lint-cvat-exchange-oracle.yaml | 2 +- .../ci-lint-cvat-recording-oracle.yaml | 2 +- .github/workflows/ci-lint.yaml | 2 +- .github/workflows/ci-test-core.yaml | 2 +- .../ci-test-cvat-exchange-oracle.yaml | 2 +- .../ci-test-cvat-recording-oracle.yaml | 2 +- .github/workflows/ci-test-dashboard.yaml | 2 +- .github/workflows/ci-test-faucet-server.yaml | 2 +- .github/workflows/ci-test-fortune.yaml | 2 +- .github/workflows/ci-test-human-app.yaml | 2 +- .github/workflows/ci-test-job-launcher.yaml | 2 +- .github/workflows/ci-test-node-sdk.yaml | 2 +- .github/workflows/ci-test-python-sdk.yaml | 2 +- .../workflows/ci-test-reputation-oracle.yaml | 2 +- .github/workflows/ci-test-subgraph.yaml | 2 +- packages/apps/dashboard/server/package.json | 2 +- packages/apps/faucet/server/package.json | 2 +- .../exchange-oracle/server/package.json | 2 +- ...dEscrowCompletedEventTypeToWebhookTable.ts | 4 +- ...6264-UpdateWebhookEnumValuesToLowerCase.ts | 4 +- .../1733127731356-AddRewardTokenToJobTable.ts | 4 +- .../fortune/recording-oracle/package.json | 2 +- .../should-navigate-to-registration.ts | 2 +- .../shared/components/data-entry/input.tsx | 6 +- packages/apps/human-app/server/package.json | 2 +- .../apps/job-launcher/server/package.json | 2 +- .../src/common/validators/token-decimals.ts | 4 +- ...updateJobStatusAndWebhookOracleTypeEnum.ts | 4 +- ...28411922919-updateEnumValuesToLowerCase.ts | 4 +- ...2497937-addJobTypeToJobsRequestTypeEnum.ts | 4 +- ...1773586440-addContentModerationRequests.ts | 4 +- ...48612934037-removeNullableFromJobEntity.ts | 4 +- ...9498615107-RenameStripeCustomerIdColumn.ts | 4 +- ...56902190591-addAudioAttributeAnnotation.ts | 4 +- .../reputation-oracle/server/package.json | 2 +- .../escrow-results-processor.ts | 6 +- .../modules/storage/storage.service.spec.ts | 1 + packages/examples/gcv/package.json | 2 +- .../human-protocol-sdk/src/graphql/types.ts | 6 +- yarn.lock | 1115 +++++++++-------- 47 files changed, 677 insertions(+), 562 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e1cb2b3671..fb3d949be6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,6 +14,13 @@ updates: schedule: interval: "weekly" target-branch: "develop" + ignore: + # Ignore versions of Jest and related packages that are equal to + # or greater than 30.0.0 because it introduces module system change + # and it must be updated together with some other packages (nest, ts-jest, etc.) + # including some extra configuration changes + - dependency-name: "*jest*" + versions: [">=30.0.0"] # Maintain dependencies for pip - package-ecosystem: "pip" diff --git a/.github/workflows/cd-cvat-exchange-oracle.yaml b/.github/workflows/cd-cvat-exchange-oracle.yaml index e77b4c3931..7888b0c225 100644 --- a/.github/workflows/cd-cvat-exchange-oracle.yaml +++ b/.github/workflows/cd-cvat-exchange-oracle.yaml @@ -3,7 +3,6 @@ name: Deploy CVAT Exchange Oracle on: push: branches: [ develop, main, cvat-milestone-2 ] - tags-ignore: '*' paths: - 'packages/examples/cvat/exchange-oracle/**' pull_request: diff --git a/.github/workflows/cd-cvat-recording-oracle.yaml b/.github/workflows/cd-cvat-recording-oracle.yaml index a4f66686a6..0a594f2704 100644 --- a/.github/workflows/cd-cvat-recording-oracle.yaml +++ b/.github/workflows/cd-cvat-recording-oracle.yaml @@ -3,7 +3,6 @@ name: Deploy CVAT Recording Oracle on: push: branches: [ develop, main, cvat-milestone-2 ] - tags-ignore: '*' paths: - 'packages/examples/cvat/recording-oracle/**' pull_request: diff --git a/.github/workflows/cd-job-launcher-server.yaml b/.github/workflows/cd-job-launcher-server.yaml index 02a075af78..ec761f4ec7 100644 --- a/.github/workflows/cd-job-launcher-server.yaml +++ b/.github/workflows/cd-job-launcher-server.yaml @@ -3,7 +3,6 @@ name: Deploy Job launcher server on: push: branches: [ develop, main ] - tags-ignore: '*' paths: - 'packages/apps/job-launcher/server/**' pull_request: diff --git a/.github/workflows/cd-packages.yaml b/.github/workflows/cd-packages.yaml index ea030917e4..8aea8c284a 100644 --- a/.github/workflows/cd-packages.yaml +++ b/.github/workflows/cd-packages.yaml @@ -18,7 +18,6 @@ on: push: branches: - main - tags-ignore: '*' paths-ignore: - "docs/**" - "packages/apps/**" diff --git a/.github/workflows/cd-python-sdk.yaml b/.github/workflows/cd-python-sdk.yaml index 2af293b225..dca5e340a5 100644 --- a/.github/workflows/cd-python-sdk.yaml +++ b/.github/workflows/cd-python-sdk.yaml @@ -13,7 +13,6 @@ on: push: branches: - main - tags-ignore: '*' paths: - "packages/sdk/python/human-protocol-sdk/**" diff --git a/.github/workflows/cd-reputation-oracle.yaml b/.github/workflows/cd-reputation-oracle.yaml index 396733e638..e107727447 100644 --- a/.github/workflows/cd-reputation-oracle.yaml +++ b/.github/workflows/cd-reputation-oracle.yaml @@ -3,7 +3,6 @@ name: Deploy Reputation oracle on: push: branches: [ develop, main ] - tags-ignore: '*' paths: - 'packages/apps/reputation-oracle/server/**' pull_request: diff --git a/.github/workflows/ci-lint-cvat-exchange-oracle.yaml b/.github/workflows/ci-lint-cvat-exchange-oracle.yaml index 22525975c8..9c6661e9b7 100644 --- a/.github/workflows/ci-lint-cvat-exchange-oracle.yaml +++ b/.github/workflows/ci-lint-cvat-exchange-oracle.yaml @@ -2,7 +2,7 @@ name: CVAT Exchange Oracle Lint on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/examples/cvat/exchange-oracle/**' - '.github/workflows/ci-lint-cvat-exchange-oracle.yaml' diff --git a/.github/workflows/ci-lint-cvat-recording-oracle.yaml b/.github/workflows/ci-lint-cvat-recording-oracle.yaml index 7d4e0390f1..a025513ba8 100644 --- a/.github/workflows/ci-lint-cvat-recording-oracle.yaml +++ b/.github/workflows/ci-lint-cvat-recording-oracle.yaml @@ -2,7 +2,7 @@ name: CVAT Recording Oracle Lint on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/examples/cvat/recording-oracle/**' - '.github/workflows/ci-lint-cvat-recording-oracle.yaml' diff --git a/.github/workflows/ci-lint.yaml b/.github/workflows/ci-lint.yaml index f9b87355b8..1f67fd3169 100644 --- a/.github/workflows/ci-lint.yaml +++ b/.github/workflows/ci-lint.yaml @@ -2,7 +2,7 @@ name: Lint check on: push: - tags-ignore: '*' + branches: '**' paths-ignore: - 'packages/examples/cvat/**' diff --git a/.github/workflows/ci-test-core.yaml b/.github/workflows/ci-test-core.yaml index e8c8953b2d..f3bf6c8f9c 100644 --- a/.github/workflows/ci-test-core.yaml +++ b/.github/workflows/ci-test-core.yaml @@ -2,7 +2,7 @@ name: Protocol check on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/core/**' diff --git a/.github/workflows/ci-test-cvat-exchange-oracle.yaml b/.github/workflows/ci-test-cvat-exchange-oracle.yaml index f5e28dec2c..c9f892d133 100644 --- a/.github/workflows/ci-test-cvat-exchange-oracle.yaml +++ b/.github/workflows/ci-test-cvat-exchange-oracle.yaml @@ -2,7 +2,7 @@ name: CVAT Exchange Oracle Tests on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/examples/cvat/exchange-oracle/**' - 'packages/sdk/python/human-protocol-sdk/**' diff --git a/.github/workflows/ci-test-cvat-recording-oracle.yaml b/.github/workflows/ci-test-cvat-recording-oracle.yaml index 38d5f39f75..590120a277 100644 --- a/.github/workflows/ci-test-cvat-recording-oracle.yaml +++ b/.github/workflows/ci-test-cvat-recording-oracle.yaml @@ -2,7 +2,7 @@ name: CVAT Recording Oracle Tests on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/examples/cvat/recording-oracle/**' - 'packages/core/**' diff --git a/.github/workflows/ci-test-dashboard.yaml b/.github/workflows/ci-test-dashboard.yaml index aeb06fe38d..85a1cbdb7a 100644 --- a/.github/workflows/ci-test-dashboard.yaml +++ b/.github/workflows/ci-test-dashboard.yaml @@ -2,7 +2,7 @@ name: Dashboard Check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/human-protocol-sdk/**" diff --git a/.github/workflows/ci-test-faucet-server.yaml b/.github/workflows/ci-test-faucet-server.yaml index 93c53d226c..b93b8e9197 100644 --- a/.github/workflows/ci-test-faucet-server.yaml +++ b/.github/workflows/ci-test-faucet-server.yaml @@ -2,7 +2,7 @@ name: Faucet server check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/human-protocol-sdk/**" diff --git a/.github/workflows/ci-test-fortune.yaml b/.github/workflows/ci-test-fortune.yaml index 497848d717..86df190e5c 100644 --- a/.github/workflows/ci-test-fortune.yaml +++ b/.github/workflows/ci-test-fortune.yaml @@ -2,7 +2,7 @@ name: Fortune check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/human-protocol-sdk/**" diff --git a/.github/workflows/ci-test-human-app.yaml b/.github/workflows/ci-test-human-app.yaml index b1b8db3183..2c32e1c0f1 100644 --- a/.github/workflows/ci-test-human-app.yaml +++ b/.github/workflows/ci-test-human-app.yaml @@ -2,7 +2,7 @@ name: Human App Check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/human-protocol-sdk/**" diff --git a/.github/workflows/ci-test-job-launcher.yaml b/.github/workflows/ci-test-job-launcher.yaml index e3c8cbc85e..6c64f8dd2f 100644 --- a/.github/workflows/ci-test-job-launcher.yaml +++ b/.github/workflows/ci-test-job-launcher.yaml @@ -2,7 +2,7 @@ name: Job Launcher Check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/human-protocol-sdk/**" diff --git a/.github/workflows/ci-test-node-sdk.yaml b/.github/workflows/ci-test-node-sdk.yaml index 1de6985fa3..3ad8fcd4f3 100644 --- a/.github/workflows/ci-test-node-sdk.yaml +++ b/.github/workflows/ci-test-node-sdk.yaml @@ -2,7 +2,7 @@ name: Node.js SDK check on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/core/**' - 'packages/sdk/typescript/human-protocol-sdk/**' diff --git a/.github/workflows/ci-test-python-sdk.yaml b/.github/workflows/ci-test-python-sdk.yaml index 69b7520cae..f5126f610e 100644 --- a/.github/workflows/ci-test-python-sdk.yaml +++ b/.github/workflows/ci-test-python-sdk.yaml @@ -2,7 +2,7 @@ name: Python SDK check on: push: - tags-ignore: '*' + branches: '**' paths: - 'packages/core/**' - 'packages/sdk/python/human-protocol-sdk/**' diff --git a/.github/workflows/ci-test-reputation-oracle.yaml b/.github/workflows/ci-test-reputation-oracle.yaml index 15e86cf6c3..0b68888f9e 100644 --- a/.github/workflows/ci-test-reputation-oracle.yaml +++ b/.github/workflows/ci-test-reputation-oracle.yaml @@ -2,7 +2,7 @@ name: Reputation Oracle Check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/human-protocol-sdk/**" diff --git a/.github/workflows/ci-test-subgraph.yaml b/.github/workflows/ci-test-subgraph.yaml index 37c7d68da4..b02d7e38a0 100644 --- a/.github/workflows/ci-test-subgraph.yaml +++ b/.github/workflows/ci-test-subgraph.yaml @@ -2,7 +2,7 @@ name: Subgraph check on: push: - tags-ignore: '*' + branches: '**' paths: - "packages/core/**" - "packages/sdk/typescript/subgraph/**" diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 2f12644ba2..3db3938026 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -52,7 +52,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "jest": "30.2.0", + "jest": "^29.7.0", "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", diff --git a/packages/apps/faucet/server/package.json b/packages/apps/faucet/server/package.json index 0fbd758582..9441a70e1b 100644 --- a/packages/apps/faucet/server/package.json +++ b/packages/apps/faucet/server/package.json @@ -31,7 +31,7 @@ "concurrently": "^9.1.2", "eslint": "^9.39.1", "hardhat": "^2.26.0", - "jest": "^30.2.0", + "jest": "^29.7.0", "ts-node": "^10.9.2", "typescript": "^5.8.3" } diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 6b50cffec5..5357d7d6c0 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -77,7 +77,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "jest": "30.2.0", + "jest": "^29.7.0", "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", diff --git a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1720453476309-AddEscrowCompletedEventTypeToWebhookTable.ts b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1720453476309-AddEscrowCompletedEventTypeToWebhookTable.ts index 9886b01111..ffe817a50c 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1720453476309-AddEscrowCompletedEventTypeToWebhookTable.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1720453476309-AddEscrowCompletedEventTypeToWebhookTable.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class AddEscrowCompletedEventTypeToWebhookTable1720453476309 - implements MigrationInterface -{ +export class AddEscrowCompletedEventTypeToWebhookTable1720453476309 implements MigrationInterface { name = 'AddEscrowCompletedEventTypeToWebhookTable1720453476309'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1728641716264-UpdateWebhookEnumValuesToLowerCase.ts b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1728641716264-UpdateWebhookEnumValuesToLowerCase.ts index cc8779f82f..af432e63bd 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1728641716264-UpdateWebhookEnumValuesToLowerCase.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1728641716264-UpdateWebhookEnumValuesToLowerCase.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class UpdateWebhookEnumValuesToLowerCase1728641716264 - implements MigrationInterface -{ +export class UpdateWebhookEnumValuesToLowerCase1728641716264 implements MigrationInterface { name = 'UpdateWebhookEnumValuesToLowerCase1728641716264'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts index 119a4e39e2..6793412dc6 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/database/migrations/1733127731356-AddRewardTokenToJobTable.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class AddRewardTokenToJobTable1733127731356 - implements MigrationInterface -{ +export class AddRewardTokenToJobTable1733127731356 implements MigrationInterface { name = 'AddRewardTokenToJobTable1733127731356'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/fortune/recording-oracle/package.json b/packages/apps/fortune/recording-oracle/package.json index 9fc5582d36..2561c13d73 100644 --- a/packages/apps/fortune/recording-oracle/package.json +++ b/packages/apps/fortune/recording-oracle/package.json @@ -51,7 +51,7 @@ "eslint": "^9.39.1", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "jest": "^30.2.0", + "jest": "^29.7.0", "prettier": "^3.7.4", "ts-node": "^10.9.2", "typescript": "^5.8.3" diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts index 964fa16590..8bd98d3628 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts @@ -10,5 +10,5 @@ export const shouldNavigateToRegistration = ( ): boolean => Boolean( oracle.registrationNeeded && - !registrationData?.oracle_addresses.includes(oracle.address) + !registrationData?.oracle_addresses.includes(oracle.address) ); diff --git a/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx b/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx index 6c0e1ee35e..4a8c8ada84 100644 --- a/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx +++ b/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx @@ -5,8 +5,10 @@ import { Typography } from '@mui/material'; import { type InputMask } from '@/shared/components/data-entry/input-masks'; import { useColorMode } from '@/shared/contexts/color-mode'; -export interface InputProps - extends Omit { +export interface InputProps extends Omit< + TextFieldProps, + 'name' | 'error' | 'helperText' +> { name: string; label?: string; autoComplete?: string; diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index cff0252a8f..be897da044 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -69,7 +69,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "jest": "30.2.0", + "jest": "^29.7.0", "nock": "^13.5.1", "prettier": "^3.7.4", "source-map-support": "^0.5.20", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index 174d6ada53..a9e88d937c 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -91,7 +91,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", - "jest": "30.2.0", + "jest": "^29.7.0", "prettier": "^3.7.4", "source-map-support": "^0.5.20", "ts-jest": "29.2.5", diff --git a/packages/apps/job-launcher/server/src/common/validators/token-decimals.ts b/packages/apps/job-launcher/server/src/common/validators/token-decimals.ts index 94ed779493..b550803482 100644 --- a/packages/apps/job-launcher/server/src/common/validators/token-decimals.ts +++ b/packages/apps/job-launcher/server/src/common/validators/token-decimals.ts @@ -10,9 +10,7 @@ import { ChainId } from '@human-protocol/sdk'; import { PaymentCurrency } from '../enums/payment'; @ValidatorConstraint({ async: false }) -export class IsValidTokenDecimalsConstraint - implements ValidatorConstraintInterface -{ +export class IsValidTokenDecimalsConstraint implements ValidatorConstraintInterface { validate(value: number, args: ValidationArguments) { const [tokenProperty] = args.constraints; const dto = args.object as Record; diff --git a/packages/apps/job-launcher/server/src/database/migrations/1703041584469-updateJobStatusAndWebhookOracleTypeEnum.ts b/packages/apps/job-launcher/server/src/database/migrations/1703041584469-updateJobStatusAndWebhookOracleTypeEnum.ts index 6a879a1fc7..0edab37578 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1703041584469-updateJobStatusAndWebhookOracleTypeEnum.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1703041584469-updateJobStatusAndWebhookOracleTypeEnum.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class UpdateJobStatusAndWebhookOracleTypeEnum1703041584469 - implements MigrationInterface -{ +export class UpdateJobStatusAndWebhookOracleTypeEnum1703041584469 implements MigrationInterface { name = 'UpdateJobStatusAndWebhookOracleTypeEnum1703041584469'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1728411922919-updateEnumValuesToLowerCase.ts b/packages/apps/job-launcher/server/src/database/migrations/1728411922919-updateEnumValuesToLowerCase.ts index 9eb2c39567..b8db65c28e 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1728411922919-updateEnumValuesToLowerCase.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1728411922919-updateEnumValuesToLowerCase.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class UpdateWebhookEnumValuesToLowerCase1728411922919 - implements MigrationInterface -{ +export class UpdateWebhookEnumValuesToLowerCase1728411922919 implements MigrationInterface { name = 'UpdateWebhookEnumValuesToLowerCase1728411922919'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1732612497937-addJobTypeToJobsRequestTypeEnum.ts b/packages/apps/job-launcher/server/src/database/migrations/1732612497937-addJobTypeToJobsRequestTypeEnum.ts index fb95b60f41..9d315fec24 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1732612497937-addJobTypeToJobsRequestTypeEnum.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1732612497937-addJobTypeToJobsRequestTypeEnum.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class AddJobTypeToJobsRequestTypeEnum1732612497937 - implements MigrationInterface -{ +export class AddJobTypeToJobsRequestTypeEnum1732612497937 implements MigrationInterface { name = 'AddJobTypeToJobsRequestTypeEnum1732612497937'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1741773586440-addContentModerationRequests.ts b/packages/apps/job-launcher/server/src/database/migrations/1741773586440-addContentModerationRequests.ts index 7163fcac46..b71553b5d6 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1741773586440-addContentModerationRequests.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1741773586440-addContentModerationRequests.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class AddContentModerationRequests1741773586440 - implements MigrationInterface -{ +export class AddContentModerationRequests1741773586440 implements MigrationInterface { name = 'AddContentModerationRequests1741773586440'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1748612934037-removeNullableFromJobEntity.ts b/packages/apps/job-launcher/server/src/database/migrations/1748612934037-removeNullableFromJobEntity.ts index 1463a83345..edadb4656f 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1748612934037-removeNullableFromJobEntity.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1748612934037-removeNullableFromJobEntity.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class RemoveNullableFromJobEntity1748612934037 - implements MigrationInterface -{ +export class RemoveNullableFromJobEntity1748612934037 implements MigrationInterface { name = 'RemoveNullableFromJobEntity1748612934037'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1749498615107-RenameStripeCustomerIdColumn.ts b/packages/apps/job-launcher/server/src/database/migrations/1749498615107-RenameStripeCustomerIdColumn.ts index adb2f1fd30..b2f1d28fdd 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1749498615107-RenameStripeCustomerIdColumn.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1749498615107-RenameStripeCustomerIdColumn.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class RenameStripeCustomerIdColumn1749498615107 - implements MigrationInterface -{ +export class RenameStripeCustomerIdColumn1749498615107 implements MigrationInterface { name = 'RenameStripeCustomerIdColumn1749498615107'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/job-launcher/server/src/database/migrations/1756902190591-addAudioAttributeAnnotation.ts b/packages/apps/job-launcher/server/src/database/migrations/1756902190591-addAudioAttributeAnnotation.ts index bcdf41aca0..95b4fe21ee 100644 --- a/packages/apps/job-launcher/server/src/database/migrations/1756902190591-addAudioAttributeAnnotation.ts +++ b/packages/apps/job-launcher/server/src/database/migrations/1756902190591-addAudioAttributeAnnotation.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class AddAudioAttributeAnnotation1756902190591 - implements MigrationInterface -{ +export class AddAudioAttributeAnnotation1756902190591 implements MigrationInterface { name = 'AddAudioAttributeAnnotation1756902190591'; public async up(queryRunner: QueryRunner): Promise { diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 5997ed8aea..01f6349d1e 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -91,7 +91,7 @@ "eslint-plugin-import": "^2.32.0", "eslint-plugin-prettier": "^5.5.4", "globals": "^16.3.0", - "jest": "30.2.0", + "jest": "^29.7.0", "nock": "^14.0.3", "prettier": "^3.7.4", "ts-jest": "29.2.5", diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/escrow-results-processor.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/escrow-results-processor.ts index e93938056d..f0d5ece5dd 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/escrow-results-processor.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/results-processing/escrow-results-processor.ts @@ -28,9 +28,9 @@ export interface EscrowResultsProcessor { } @Injectable() -export abstract class BaseEscrowResultsProcessor - implements EscrowResultsProcessor -{ +export abstract class BaseEscrowResultsProcessor< + TManifest extends JobManifest, +> implements EscrowResultsProcessor { constructor( private readonly storageService: StorageService, private readonly pgpEncryptionService: PgpEncryptionService, diff --git a/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.spec.ts index 9c8864a012..275cd853d5 100644 --- a/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.spec.ts @@ -137,6 +137,7 @@ describe('StorageService', () => { mockS3ConfigService.bucket, fileName, fileContent, + undefined, { 'Content-Type': contentType, 'Cache-Control': 'no-store', diff --git a/packages/examples/gcv/package.json b/packages/examples/gcv/package.json index e3c5389ff9..8d8946ddc7 100644 --- a/packages/examples/gcv/package.json +++ b/packages/examples/gcv/package.json @@ -21,7 +21,7 @@ "@types/xml2js": "^0.4.14", "eslint": "^9.39.1", "eslint-plugin-jest": "^28.9.0", - "jest": "^30.2.0", + "jest": "^29.7.0", "typescript": "^5.8.3" } } diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts index 79023a88e4..fed501218f 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts @@ -166,8 +166,10 @@ export interface IOperatorSubgraph { } | null; } -export interface IReputationNetworkSubgraph - extends Omit { +export interface IReputationNetworkSubgraph extends Omit< + IReputationNetwork, + 'operators' +> { operators: IOperatorSubgraph[]; } diff --git a/yarn.lock b/yarn.lock index a9d4c303c0..f9e60501bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -182,7 +182,7 @@ __metadata: eslint-plugin-jest: "npm:^28.9.0" eslint-plugin-prettier: "npm:^5.2.1" ethers: "npm:~6.15.0" - jest: "npm:30.2.0" + jest: "npm:^29.7.0" lodash: "npm:^4.17.21" prettier: "npm:^3.7.4" reflect-metadata: "npm:^0.2.2" @@ -240,7 +240,7 @@ __metadata: express: "npm:^4.21.0" express-rate-limit: "npm:^7.3.0" hardhat: "npm:^2.26.0" - jest: "npm:^30.2.0" + jest: "npm:^29.7.0" node-cache: "npm:^5.1.2" ts-node: "npm:^10.9.2" typescript: "npm:^5.8.3" @@ -324,7 +324,7 @@ __metadata: eslint-plugin-jest: "npm:^28.9.0" eslint-plugin-prettier: "npm:^5.2.1" ethers: "npm:~6.15.0" - jest: "npm:30.2.0" + jest: "npm:^29.7.0" joi: "npm:^17.13.3" jsonwebtoken: "npm:^9.0.2" minio: "npm:8.0.6" @@ -370,7 +370,7 @@ __metadata: eslint-plugin-jest: "npm:^28.9.0" eslint-plugin-prettier: "npm:^5.2.1" helmet: "npm:^7.1.0" - jest: "npm:^30.2.0" + jest: "npm:^29.7.0" joi: "npm:^17.13.3" minio: "npm:8.0.6" prettier: "npm:^3.7.4" @@ -392,7 +392,7 @@ __metadata: dotenv: "npm:^17.2.2" eslint: "npm:^9.39.1" eslint-plugin-jest: "npm:^28.9.0" - jest: "npm:^30.2.0" + jest: "npm:^29.7.0" typescript: "npm:^5.8.3" xml2js: "npm:^0.6.2" languageName: unknown @@ -510,7 +510,7 @@ __metadata: eslint-plugin-jest: "npm:^28.9.0" eslint-plugin-prettier: "npm:^5.2.1" ethers: "npm:^6.15.0" - jest: "npm:30.2.0" + jest: "npm:^29.7.0" joi: "npm:^17.13.3" jsonwebtoken: "npm:^9.0.2" jwt-decode: "npm:^4.0.0" @@ -635,7 +635,7 @@ __metadata: eslint-plugin-jest: "npm:^28.9.0" eslint-plugin-prettier: "npm:^5.2.1" helmet: "npm:^7.1.0" - jest: "npm:30.2.0" + jest: "npm:^29.7.0" joi: "npm:^17.13.3" json-stable-stringify: "npm:^1.2.1" minio: "npm:8.0.6" @@ -710,7 +710,7 @@ __metadata: ethers: "npm:~6.15.0" globals: "npm:^16.3.0" helmet: "npm:^7.1.0" - jest: "npm:30.2.0" + jest: "npm:^29.7.0" joi: "npm:^17.13.3" json-stable-stringify: "npm:^1.2.1" lodash: "npm:^4.17.21" @@ -1351,7 +1351,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.27.1": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.27.1": version: 7.27.1 resolution: "@babel/code-frame@npm:7.27.1" dependencies: @@ -1369,7 +1369,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.16.0, @babel/core@npm:^7.21.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.0, @babel/core@npm:^7.27.4, @babel/core@npm:^7.28.0": +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.21.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.0, @babel/core@npm:^7.28.0": version: 7.28.5 resolution: "@babel/core@npm:7.28.5" dependencies: @@ -1406,7 +1406,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.28.5": +"@babel/generator@npm:^7.28.5, @babel/generator@npm:^7.7.2": version: 7.28.5 resolution: "@babel/generator@npm:7.28.5" dependencies: @@ -1620,7 +1620,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.5": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.5": version: 7.28.5 resolution: "@babel/parser@npm:7.28.5" dependencies: @@ -1897,7 +1897,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.27.1": +"@babel/plugin-syntax-jsx@npm:^7.27.1, @babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.27.1 resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" dependencies: @@ -1996,7 +1996,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.27.1": +"@babel/plugin-syntax-typescript@npm:^7.27.1, @babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.27.1 resolution: "@babel/plugin-syntax-typescript@npm:7.27.1" dependencies: @@ -2874,7 +2874,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2": +"@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": version: 7.27.2 resolution: "@babel/template@npm:7.27.2" dependencies: @@ -2900,7 +2900,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5, @babel/types@npm:^7.4.4": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": version: 7.28.5 resolution: "@babel/types@npm:7.28.5" dependencies: @@ -5367,58 +5367,58 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/console@npm:30.2.0" +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" dependencies: - "@jest/types": "npm:30.2.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - chalk: "npm:^4.1.2" - jest-message-util: "npm:30.2.0" - jest-util: "npm:30.2.0" + chalk: "npm:^4.0.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" slash: "npm:^3.0.0" - checksum: 10c0/ecf7ca43698863095500710a5aa08c38b1731c9d89ba32f4d9da7424b53ce1e86b3db8ccbbb27b695f49b4f94bc1d7d0c63c751d73c83d59488a682bc98b7e70 + checksum: 10c0/7be408781d0a6f657e969cbec13b540c329671819c2f57acfad0dae9dbfe2c9be859f38fe99b35dba9ff1536937dc6ddc69fdcd2794812fa3c647a1619797f6c languageName: node linkType: hard -"@jest/core@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/core@npm:30.2.0" +"@jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" dependencies: - "@jest/console": "npm:30.2.0" - "@jest/pattern": "npm:30.0.1" - "@jest/reporters": "npm:30.2.0" - "@jest/test-result": "npm:30.2.0" - "@jest/transform": "npm:30.2.0" - "@jest/types": "npm:30.2.0" + "@jest/console": "npm:^29.7.0" + "@jest/reporters": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-changed-files: "npm:30.2.0" - jest-config: "npm:30.2.0" - jest-haste-map: "npm:30.2.0" - jest-message-util: "npm:30.2.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.2.0" - jest-resolve-dependencies: "npm:30.2.0" - jest-runner: "npm:30.2.0" - jest-runtime: "npm:30.2.0" - jest-snapshot: "npm:30.2.0" - jest-util: "npm:30.2.0" - jest-validate: "npm:30.2.0" - jest-watcher: "npm:30.2.0" - micromatch: "npm:^4.0.8" - pretty-format: "npm:30.2.0" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-changed-files: "npm:^29.7.0" + jest-config: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-resolve-dependencies: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" slash: "npm:^3.0.0" + strip-ansi: "npm:^6.0.0" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - checksum: 10c0/03b3e35df3bbbbe28e2b53c0fe82d39b748d99b3bc88bb645c76593cdca44d7115f03ef6e6a1715f0862151d0ebab496199283def248fc05eb520f6aec6b20f3 + checksum: 10c0/934f7bf73190f029ac0f96662c85cd276ec460d407baf6b0dbaec2872e157db4d55a7ee0b1c43b18874602f662b37cb973dda469a4e6d88b4e4845b521adeeb2 languageName: node linkType: hard @@ -5429,15 +5429,15 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/environment@npm:30.2.0" +"@jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" dependencies: - "@jest/fake-timers": "npm:30.2.0" - "@jest/types": "npm:30.2.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - jest-mock: "npm:30.2.0" - checksum: 10c0/56a9f1b82ee2623c13eece7d58188be35bd6e5c3c4ee3fbaedb1c4d7242c1b57d020f1a26ab127fa9496fdc11306c7ad1c4a2b7eba1fc726a27ae0873e907e47 + jest-mock: "npm:^29.7.0" + checksum: 10c0/c7b1b40c618f8baf4d00609022d2afa086d9c6acc706f303a70bb4b67275868f620ad2e1a9efc5edd418906157337cce50589a627a6400bbdf117d351b91ef86 languageName: node linkType: hard @@ -5450,27 +5450,36 @@ __metadata: languageName: node linkType: hard -"@jest/expect@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/expect@npm:30.2.0" +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" dependencies: - expect: "npm:30.2.0" - jest-snapshot: "npm:30.2.0" - checksum: 10c0/3984879022780dd480301c560cef465156b29d610f2c698fcdf81ad76930411d7816eff7cb721e81a1d9aaa8c2240a73c20be9385d1978c14b405a2ac6c9104a + jest-get-type: "npm:^29.6.3" + checksum: 10c0/60b79d23a5358dc50d9510d726443316253ecda3a7fb8072e1526b3e0d3b14f066ee112db95699b7a43ad3f0b61b750c72e28a5a1cac361d7a2bb34747fa938a languageName: node linkType: hard -"@jest/fake-timers@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/fake-timers@npm:30.2.0" +"@jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" dependencies: - "@jest/types": "npm:30.2.0" - "@sinonjs/fake-timers": "npm:^13.0.0" + expect: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + checksum: 10c0/b41f193fb697d3ced134349250aed6ccea075e48c4f803159db102b826a4e473397c68c31118259868fd69a5cba70e97e1c26d2c2ff716ca39dc73a2ccec037e + languageName: node + linkType: hard + +"@jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@sinonjs/fake-timers": "npm:^10.0.2" "@types/node": "npm:*" - jest-message-util: "npm:30.2.0" - jest-mock: "npm:30.2.0" - jest-util: "npm:30.2.0" - checksum: 10c0/b29505528e546f08489535814f7dfcd3a2318660b987d605f44d41672e91a0c8c0dfc01e3dd1302e66e511409c3012d41e2e16703b214502b54ccc023773e3dc + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/cf0a8bcda801b28dc2e2b2ba36302200ee8104a45ad7a21e6c234148932f826cb3bc57c8df3b7b815aeea0861d7b6ca6f0d4778f93b9219398ef28749e03595c languageName: node linkType: hard @@ -5481,15 +5490,15 @@ __metadata: languageName: node linkType: hard -"@jest/globals@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/globals@npm:30.2.0" +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" dependencies: - "@jest/environment": "npm:30.2.0" - "@jest/expect": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - jest-mock: "npm:30.2.0" - checksum: 10c0/7433a501e3122e94b24a7bacc44fdc3921b20abf67c9d795f5bdd169f1beac058cff8109e4fddf71fdc8b18e532cb88c55412ca9927966f354930d6bb3fcaf9c + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + jest-mock: "npm:^29.7.0" + checksum: 10c0/a385c99396878fe6e4460c43bd7bb0a5cc52befb462cc6e7f2a3810f9e7bcce7cdeb51908fd530391ee452dc856c98baa2c5f5fa8a5b30b071d31ef7f6955cea languageName: node linkType: hard @@ -5503,39 +5512,40 @@ __metadata: languageName: node linkType: hard -"@jest/reporters@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/reporters@npm:30.2.0" +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" dependencies: "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:30.2.0" - "@jest/test-result": "npm:30.2.0" - "@jest/transform": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - "@jridgewell/trace-mapping": "npm:^0.3.25" + "@jest/console": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@jridgewell/trace-mapping": "npm:^0.3.18" "@types/node": "npm:*" - chalk: "npm:^4.1.2" - collect-v8-coverage: "npm:^1.0.2" - exit-x: "npm:^0.2.2" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.11" + chalk: "npm:^4.0.0" + collect-v8-coverage: "npm:^1.0.0" + exit: "npm:^0.1.2" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" istanbul-lib-coverage: "npm:^3.0.0" istanbul-lib-instrument: "npm:^6.0.0" istanbul-lib-report: "npm:^3.0.0" - istanbul-lib-source-maps: "npm:^5.0.0" + istanbul-lib-source-maps: "npm:^4.0.0" istanbul-reports: "npm:^3.1.3" - jest-message-util: "npm:30.2.0" - jest-util: "npm:30.2.0" - jest-worker: "npm:30.2.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" slash: "npm:^3.0.0" - string-length: "npm:^4.0.2" + string-length: "npm:^4.0.1" + strip-ansi: "npm:^6.0.0" v8-to-istanbul: "npm:^9.0.1" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - checksum: 10c0/1f25d0896f857f220466cae3145a20f9e13e7d73aeccf87a1f8a5accb42bb7a564864ba63befa3494d76d1335b86c24d66054d62330c3dcffc9c2c5f4e740d6e + checksum: 10c0/a754402a799541c6e5aff2c8160562525e2a47e7d568f01ebfc4da66522de39cbb809bbb0a841c7052e4270d79214e70aec3c169e4eae42a03bc1a8a20cb9fa2 languageName: node linkType: hard @@ -5557,73 +5567,61 @@ __metadata: languageName: node linkType: hard -"@jest/snapshot-utils@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/snapshot-utils@npm:30.2.0" - dependencies: - "@jest/types": "npm:30.2.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - natural-compare: "npm:^1.4.0" - checksum: 10c0/df69ee3b95d64db6d1e79e39d5dc226e417b412a1d5113264b487eb3a8887366a7952c350c378e2292f8e83ec1b3be22040317b795e85eb431830cbde06d09d8 - languageName: node - linkType: hard - -"@jest/source-map@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/source-map@npm:30.0.1" +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.25" - callsites: "npm:^3.1.0" - graceful-fs: "npm:^4.2.11" - checksum: 10c0/e7bda2786fc9f483d9dd7566c58c4bd948830997be862dfe80a3ae5550ff3f84753abb52e705d02ebe9db9f34ba7ebec4c2db11882048cdeef7a66f6332b3897 + "@jridgewell/trace-mapping": "npm:^0.3.18" + callsites: "npm:^3.0.0" + graceful-fs: "npm:^4.2.9" + checksum: 10c0/a2f177081830a2e8ad3f2e29e20b63bd40bade294880b595acf2fc09ec74b6a9dd98f126a2baa2bf4941acd89b13a4ade5351b3885c224107083a0059b60a219 languageName: node linkType: hard -"@jest/test-result@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/test-result@npm:30.2.0" +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" dependencies: - "@jest/console": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - collect-v8-coverage: "npm:^1.0.2" - checksum: 10c0/87566d56b4f90630282c103f41ea9031f4647902f2cd9839bc49af6248301c1a95cbc4432a9512e61f6c6d778e8b925d0573588b26a211d3198c62471ba08c81 + "@jest/console": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/istanbul-lib-coverage": "npm:^2.0.0" + collect-v8-coverage: "npm:^1.0.0" + checksum: 10c0/7de54090e54a674ca173470b55dc1afdee994f2d70d185c80236003efd3fa2b753fff51ffcdda8e2890244c411fd2267529d42c4a50a8303755041ee493e6a04 languageName: node linkType: hard -"@jest/test-sequencer@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/test-sequencer@npm:30.2.0" +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" dependencies: - "@jest/test-result": "npm:30.2.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.2.0" + "@jest/test-result": "npm:^29.7.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" slash: "npm:^3.0.0" - checksum: 10c0/b8366e629b885bfc4b2b95f34f47405e70120eb8601f42de20ea4de308a5088d7bd9f535abf67a2a0d083a2b49864176e1333e036426a5d6b6bd02c1c4dda40b + checksum: 10c0/593a8c4272797bb5628984486080cbf57aed09c7cfdc0a634e8c06c38c6bef329c46c0016e84555ee55d1cd1f381518cf1890990ff845524c1123720c8c1481b languageName: node linkType: hard -"@jest/transform@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/transform@npm:30.2.0" +"@jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/types": "npm:30.2.0" - "@jridgewell/trace-mapping": "npm:^0.3.25" - babel-plugin-istanbul: "npm:^7.0.1" - chalk: "npm:^4.1.2" + "@babel/core": "npm:^7.11.6" + "@jest/types": "npm:^29.6.3" + "@jridgewell/trace-mapping": "npm:^0.3.18" + babel-plugin-istanbul: "npm:^6.1.1" + chalk: "npm:^4.0.0" convert-source-map: "npm:^2.0.0" fast-json-stable-stringify: "npm:^2.1.0" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.2.0" - jest-regex-util: "npm:30.0.1" - jest-util: "npm:30.2.0" - micromatch: "npm:^4.0.8" - pirates: "npm:^4.0.7" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + pirates: "npm:^4.0.4" slash: "npm:^3.0.0" - write-file-atomic: "npm:^5.0.1" - checksum: 10c0/c0f21576de9f7ad8a2647450b5cd127d7c60176c19a666230241d121b9f928b036dd19973363e4acd7db2f8b82caff2b624930f57471be6092d73a7775365606 + write-file-atomic: "npm:^4.0.2" + checksum: 10c0/7f4a7f73dcf45dfdf280c7aa283cbac7b6e5a904813c3a93ead7e55873761fc20d5c4f0191d2019004fac6f55f061c82eb3249c2901164ad80e362e7a7ede5a6 languageName: node linkType: hard @@ -5710,7 +5708,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.28": version: 0.3.31 resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: @@ -9140,7 +9138,7 @@ __metadata: languageName: node linkType: hard -"@sinonjs/commons@npm:^3.0.1": +"@sinonjs/commons@npm:^3.0.0": version: 3.0.1 resolution: "@sinonjs/commons@npm:3.0.1" dependencies: @@ -9149,12 +9147,12 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^13.0.0": - version: 13.0.5 - resolution: "@sinonjs/fake-timers@npm:13.0.5" +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" dependencies: - "@sinonjs/commons": "npm:^3.0.1" - checksum: 10c0/a707476efd523d2138ef6bba916c83c4a377a8372ef04fad87499458af9f01afc58f4f245c5fd062793d6d70587309330c6f96947b5bd5697961c18004dc3e26 + "@sinonjs/commons": "npm:^3.0.0" + checksum: 10c0/2e2fb6cc57f227912814085b7b01fede050cd4746ea8d49a1e44d5a0e56a804663b0340ae2f11af7559ea9bf4d087a11f2f646197a660ea3cb04e19efc04aa63 languageName: node linkType: hard @@ -10927,7 +10925,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.20.5": +"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -10959,7 +10957,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__traverse@npm:*": +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": version: 7.28.0 resolution: "@types/babel__traverse@npm:7.28.0" dependencies: @@ -11239,6 +11237,15 @@ __metadata: languageName: node linkType: hard +"@types/graceful-fs@npm:^4.1.3": + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/235d2fc69741448e853333b7c3d1180a966dd2b8972c8cbcd6b2a0c6cd7f8d582ab2b8e58219dbc62cce8f1b40aa317ff78ea2201cdd8249da5025adebed6f0b + languageName: node + linkType: hard + "@types/hast@npm:^3.0.4": version: 3.0.4 resolution: "@types/hast@npm:3.0.4" @@ -11675,7 +11682,7 @@ __metadata: languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.3": +"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c @@ -12467,13 +12474,6 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.3.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a - languageName: node - linkType: hard - "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": version: 1.11.1 resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" @@ -13959,7 +13959,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.2.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df @@ -13987,7 +13987,7 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:^3.1.3, anymatch@npm:~3.1.2": +"anymatch@npm:^3.0.3, anymatch@npm:^3.1.3, anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" dependencies: @@ -14486,42 +14486,45 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:30.2.0": - version: 30.2.0 - resolution: "babel-jest@npm:30.2.0" +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" dependencies: - "@jest/transform": "npm:30.2.0" - "@types/babel__core": "npm:^7.20.5" - babel-plugin-istanbul: "npm:^7.0.1" - babel-preset-jest: "npm:30.2.0" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" + "@jest/transform": "npm:^29.7.0" + "@types/babel__core": "npm:^7.1.14" + babel-plugin-istanbul: "npm:^6.1.1" + babel-preset-jest: "npm:^29.6.3" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" slash: "npm:^3.0.0" peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-0 - checksum: 10c0/673b8c87e5aec97c4f7372319c005d1e2b018e2f2e973378c7fb0a4f1e111f89872e6f1e49dd50aff6290cd881c865117ade67f2c78a356a8275ab21af47340d + "@babel/core": ^7.8.0 + checksum: 10c0/2eda9c1391e51936ca573dd1aedfee07b14c59b33dbe16ef347873ddd777bcf6e2fc739681e9e9661ab54ef84a3109a03725be2ac32cd2124c07ea4401cbe8c1 languageName: node linkType: hard -"babel-plugin-istanbul@npm:^7.0.1": - version: 7.0.1 - resolution: "babel-plugin-istanbul@npm:7.0.1" +"babel-plugin-istanbul@npm:^6.1.1": + version: 6.1.1 + resolution: "babel-plugin-istanbul@npm:6.1.1" dependencies: "@babel/helper-plugin-utils": "npm:^7.0.0" "@istanbuljs/load-nyc-config": "npm:^1.0.0" - "@istanbuljs/schema": "npm:^0.1.3" - istanbul-lib-instrument: "npm:^6.0.2" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-instrument: "npm:^5.0.4" test-exclude: "npm:^6.0.0" - checksum: 10c0/92975e3df12503b168695463b451468da0c20e117807221652eb8e33a26c160f3b9d4c5c4e65495657420e871c6a54e5e31f539e2e1da37ef2261d7ddd4b1dfd + checksum: 10c0/1075657feb705e00fd9463b329921856d3775d9867c5054b449317d39153f8fbcebd3e02ebf00432824e647faff3683a9ca0a941325ef1afe9b3c4dd51b24beb languageName: node linkType: hard -"babel-plugin-jest-hoist@npm:30.2.0": - version: 30.2.0 - resolution: "babel-plugin-jest-hoist@npm:30.2.0" +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" dependencies: - "@types/babel__core": "npm:^7.20.5" - checksum: 10c0/a2bd862aaa4875127c02e6020d3da67556a8f25981060252668dda65cf9a146202937ae80d2e8612c3c47afe19ac85577647b8cc216faa98567c685525a3f203 + "@babel/template": "npm:^7.3.3" + "@babel/types": "npm:^7.3.3" + "@types/babel__core": "npm:^7.1.14" + "@types/babel__traverse": "npm:^7.0.6" + checksum: 10c0/7e6451caaf7dce33d010b8aafb970e62f1b0c0b57f4978c37b0d457bbcf0874d75a395a102daf0bae0bd14eafb9f6e9a165ee5e899c0a4f1f3bb2e07b304ed2e languageName: node linkType: hard @@ -14579,7 +14582,7 @@ __metadata: languageName: node linkType: hard -"babel-preset-current-node-syntax@npm:^1.2.0": +"babel-preset-current-node-syntax@npm:^1.0.0": version: 1.2.0 resolution: "babel-preset-current-node-syntax@npm:1.2.0" dependencies: @@ -14604,15 +14607,15 @@ __metadata: languageName: node linkType: hard -"babel-preset-jest@npm:30.2.0": - version: 30.2.0 - resolution: "babel-preset-jest@npm:30.2.0" +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" dependencies: - babel-plugin-jest-hoist: "npm:30.2.0" - babel-preset-current-node-syntax: "npm:^1.2.0" + babel-plugin-jest-hoist: "npm:^29.6.3" + babel-preset-current-node-syntax: "npm:^1.0.0" peerDependencies: - "@babel/core": ^7.11.0 || ^8.0.0-beta.1 - checksum: 10c0/fb2727bad450256146d63b5231b83a7638e73b96c9612296a20afd65fb8c76678ef9bc6fa56e81d1303109258aeb4fccea5b96568744059e47d3c6e3ebc98bd9 + "@babel/core": ^7.0.0 + checksum: 10c0/ec5fd0276b5630b05f0c14bb97cc3815c6b31600c683ebb51372e54dcb776cff790bdeeabd5b8d01ede375a040337ccbf6a3ccd68d3a34219125945e167ad943 languageName: node linkType: hard @@ -15327,7 +15330,7 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^3.0.0, callsites@npm:^3.1.0": +"callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 @@ -15341,7 +15344,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0, camelcase@npm:^6.3.0": +"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 @@ -15637,10 +15640,10 @@ __metadata: languageName: node linkType: hard -"cjs-module-lexer@npm:^2.1.0": - version: 2.1.1 - resolution: "cjs-module-lexer@npm:2.1.1" - checksum: 10c0/813697c0ed1533f4a88bd8051d8ae1cb1b21d3ff1c6a5720353817d50c3f3f83bb2af6bd83922aae94b3ef90d64d01a6eb123fa8249f4dc7215e3afd89364f86 +"cjs-module-lexer@npm:^1.0.0": + version: 1.4.3 + resolution: "cjs-module-lexer@npm:1.4.3" + checksum: 10c0/076b3af85adc4d65dbdab1b5b240fe5b45d44fcf0ef9d429044dd94d19be5589376805c44fb2d4b3e684e5fe6a9b7cf3e426476a6507c45283c5fc6ff95240be languageName: node linkType: hard @@ -15874,7 +15877,7 @@ __metadata: languageName: node linkType: hard -"collect-v8-coverage@npm:^1.0.2": +"collect-v8-coverage@npm:^1.0.0": version: 1.0.3 resolution: "collect-v8-coverage@npm:1.0.3" checksum: 10c0/bc62ba251bcce5e3354a8f88fa6442bee56e3e612fec08d4dfcf66179b41ea0bf544b0f78c4ebc0f8050871220af95bb5c5578a6aef346feea155640582f09dc @@ -16392,6 +16395,23 @@ __metadata: languageName: node linkType: hard +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + prompts: "npm:^2.0.1" + bin: + create-jest: bin/create-jest.js + checksum: 10c0/e7e54c280692470d3398f62a6238fd396327e01c6a0757002833f06d00afc62dd7bfe04ff2b9cd145264460e6b4d1eb8386f2925b7e567f97939843b7b0e812f + languageName: node + linkType: hard + "create-require@npm:^1.1.0, create-require@npm:^1.1.1": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -16832,7 +16852,7 @@ __metadata: languageName: node linkType: hard -"dedent@npm:^1.6.0": +"dedent@npm:^1.0.0, dedent@npm:^1.6.0": version: 1.7.0 resolution: "dedent@npm:1.7.0" peerDependencies: @@ -16881,7 +16901,7 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1": +"deepmerge@npm:^4.2.2": version: 4.3.1 resolution: "deepmerge@npm:4.3.1" checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044 @@ -17076,7 +17096,7 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^3.1.0": +"detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d @@ -17090,6 +17110,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 + languageName: node + linkType: hard + "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -18690,7 +18717,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:5.1.1, execa@npm:^5.1.1": +"execa@npm:5.1.1, execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -18724,10 +18751,10 @@ __metadata: languageName: node linkType: hard -"exit-x@npm:^0.2.2": - version: 0.2.2 - resolution: "exit-x@npm:0.2.2" - checksum: 10c0/212a7a095ca5540e9581f1ef2d1d6a40df7a6027c8cc96e78ce1d16b86d1a88326d4a0eff8dff2b5ec1e68bb0c1edd5d0dfdde87df1869bf7514d4bc6a5cbd72 +"exit@npm:^0.1.2": + version: 0.1.2 + resolution: "exit@npm:0.1.2" + checksum: 10c0/71d2ad9b36bc25bb8b104b17e830b40a08989be7f7d100b13269aaae7c3784c3e6e1e88a797e9e87523993a25ba27c8958959a554535370672cfb4d824af8989 languageName: node linkType: hard @@ -18738,7 +18765,20 @@ __metadata: languageName: node linkType: hard -"expect@npm:30.2.0, expect@npm:^30.0.0": +"expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" + dependencies: + "@jest/expect-utils": "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/2eddeace66e68b8d8ee5f7be57f3014b19770caaf6815c7a08d131821da527fb8c8cb7b3dcd7c883d2d3d8d184206a4268984618032d1e4b16dc8d6596475d41 + languageName: node + linkType: hard + +"expect@npm:^30.0.0": version: 30.2.0 resolution: "expect@npm:30.2.0" dependencies: @@ -19060,7 +19100,7 @@ __metadata: languageName: node linkType: hard -"fb-watchman@npm:^2.0.2": +"fb-watchman@npm:^2.0.0": version: 2.0.2 resolution: "fb-watchman@npm:2.0.2" dependencies: @@ -19487,7 +19527,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.3, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -19497,7 +19537,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -20816,7 +20856,7 @@ __metadata: languageName: node linkType: hard -"import-local@npm:^3.2.0": +"import-local@npm:^3.0.2": version: 3.2.0 resolution: "import-local@npm:3.2.0" dependencies: @@ -21203,7 +21243,7 @@ __metadata: languageName: node linkType: hard -"is-generator-fn@npm:^2.1.0": +"is-generator-fn@npm:^2.0.0": version: 2.1.0 resolution: "is-generator-fn@npm:2.1.0" checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d @@ -21602,7 +21642,20 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": +"istanbul-lib-instrument@npm:^5.0.4": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" + dependencies: + "@babel/core": "npm:^7.12.3" + "@babel/parser": "npm:^7.14.7" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^6.3.0" + checksum: 10c0/8a1bdf3e377dcc0d33ec32fe2b6ecacdb1e4358fd0eb923d4326bb11c67622c0ceb99600a680f3dad5d29c66fc1991306081e339b4d43d0b8a2ab2e1d910a6ee + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^6.0.0": version: 6.0.3 resolution: "istanbul-lib-instrument@npm:6.0.3" dependencies: @@ -21626,14 +21679,14 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-source-maps@npm:^5.0.0": - version: 5.0.6 - resolution: "istanbul-lib-source-maps@npm:5.0.6" +"istanbul-lib-source-maps@npm:^4.0.0": + version: 4.0.1 + resolution: "istanbul-lib-source-maps@npm:4.0.1" dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.23" debug: "npm:^4.1.1" istanbul-lib-coverage: "npm:^3.0.0" - checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f + source-map: "npm:^0.6.1" + checksum: 10c0/19e4cc405016f2c906dff271a76715b3e881fa9faeb3f09a86cb99b8512b3a5ed19cadfe0b54c17ca0e54c1142c9c6de9330d65506e35873994e06634eebeb66 languageName: node linkType: hard @@ -21801,110 +21854,106 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:30.2.0": - version: 30.2.0 - resolution: "jest-changed-files@npm:30.2.0" +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" dependencies: - execa: "npm:^5.1.1" - jest-util: "npm:30.2.0" + execa: "npm:^5.0.0" + jest-util: "npm:^29.7.0" p-limit: "npm:^3.1.0" - checksum: 10c0/0ce838f8bffdadcdc19028f4b7a24c04d2f9885ee5c5c1bb4746c205cb96649934090ef6492c3dc45b1be097672b4f8043ad141278bc82f390579fa3ea4c11fe + checksum: 10c0/e071384d9e2f6bb462231ac53f29bff86f0e12394c1b49ccafbad225ce2ab7da226279a8a94f421949920bef9be7ef574fd86aee22e8adfa149be73554ab828b languageName: node linkType: hard -"jest-circus@npm:30.2.0": - version: 30.2.0 - resolution: "jest-circus@npm:30.2.0" +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" dependencies: - "@jest/environment": "npm:30.2.0" - "@jest/expect": "npm:30.2.0" - "@jest/test-result": "npm:30.2.0" - "@jest/types": "npm:30.2.0" + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - chalk: "npm:^4.1.2" + chalk: "npm:^4.0.0" co: "npm:^4.6.0" - dedent: "npm:^1.6.0" - is-generator-fn: "npm:^2.1.0" - jest-each: "npm:30.2.0" - jest-matcher-utils: "npm:30.2.0" - jest-message-util: "npm:30.2.0" - jest-runtime: "npm:30.2.0" - jest-snapshot: "npm:30.2.0" - jest-util: "npm:30.2.0" + dedent: "npm:^1.0.0" + is-generator-fn: "npm:^2.0.0" + jest-each: "npm:^29.7.0" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" p-limit: "npm:^3.1.0" - pretty-format: "npm:30.2.0" - pure-rand: "npm:^7.0.0" + pretty-format: "npm:^29.7.0" + pure-rand: "npm:^6.0.0" slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10c0/32fc88e13d3e811a9af5ca02d31f7cc742e726a0128df0b023330d6dff6ac29bf981da09937162f7c0705cf327df8d24e46de84860f6817dbc134438315c2967 + stack-utils: "npm:^2.0.3" + checksum: 10c0/8d15344cf7a9f14e926f0deed64ed190c7a4fa1ed1acfcd81e4cc094d3cc5bf7902ebb7b874edc98ada4185688f90c91e1747e0dfd7ac12463b097968ae74b5e languageName: node linkType: hard -"jest-cli@npm:30.2.0": - version: 30.2.0 - resolution: "jest-cli@npm:30.2.0" +"jest-cli@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" dependencies: - "@jest/core": "npm:30.2.0" - "@jest/test-result": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - chalk: "npm:^4.1.2" - exit-x: "npm:^0.2.2" - import-local: "npm:^3.2.0" - jest-config: "npm:30.2.0" - jest-util: "npm:30.2.0" - jest-validate: "npm:30.2.0" - yargs: "npm:^17.7.2" + "@jest/core": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + create-jest: "npm:^29.7.0" + exit: "npm:^0.1.2" + import-local: "npm:^3.0.2" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + yargs: "npm:^17.3.1" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true bin: - jest: ./bin/jest.js - checksum: 10c0/b722a98cdf7b0ff1c273dd4efbaf331d683335f1f338a76a24492574e582a4e5a12a9df66e41bf4c92c7cffe0f51b759818ecd42044cd9bbef67d40359240989 + jest: bin/jest.js + checksum: 10c0/a658fd55050d4075d65c1066364595962ead7661711495cfa1dfeecf3d6d0a8ffec532f3dbd8afbb3e172dd5fd2fb2e813c5e10256e7cf2fea766314942fb43a languageName: node linkType: hard -"jest-config@npm:30.2.0": - version: 30.2.0 - resolution: "jest-config@npm:30.2.0" +"jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" dependencies: - "@babel/core": "npm:^7.27.4" - "@jest/get-type": "npm:30.1.0" - "@jest/pattern": "npm:30.0.1" - "@jest/test-sequencer": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - babel-jest: "npm:30.2.0" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - deepmerge: "npm:^4.3.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.11" - jest-circus: "npm:30.2.0" - jest-docblock: "npm:30.2.0" - jest-environment-node: "npm:30.2.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.2.0" - jest-runner: "npm:30.2.0" - jest-util: "npm:30.2.0" - jest-validate: "npm:30.2.0" - micromatch: "npm:^4.0.8" + "@babel/core": "npm:^7.11.6" + "@jest/test-sequencer": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-jest: "npm:^29.7.0" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + deepmerge: "npm:^4.2.2" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-circus: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + micromatch: "npm:^4.0.4" parse-json: "npm:^5.2.0" - pretty-format: "npm:30.2.0" + pretty-format: "npm:^29.7.0" slash: "npm:^3.0.0" strip-json-comments: "npm:^3.1.1" peerDependencies: "@types/node": "*" - esbuild-register: ">=3.4.0" ts-node: ">=9.0.0" peerDependenciesMeta: "@types/node": optional: true - esbuild-register: - optional: true ts-node: optional: true - checksum: 10c0/f02bb747e3382cdbb5a00abd583e9118a0b4f1d9d4cad01b5cc06b7fab9b817419ec183856cd791b2e9167051cad52b3d22ea34319a28c8f3e70a5ce73d05faa + checksum: 10c0/bab23c2eda1fff06e0d104b00d6adfb1d1aabb7128441899c9bff2247bd26710b050a5364281ce8d52b46b499153bf7e3ee88b19831a8f3451f1477a0246a0f1 languageName: node linkType: hard @@ -21920,72 +21969,91 @@ __metadata: languageName: node linkType: hard -"jest-docblock@npm:30.2.0": - version: 30.2.0 - resolution: "jest-docblock@npm:30.2.0" +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" dependencies: - detect-newline: "npm:^3.1.0" - checksum: 10c0/2578366604eef1b36d59ffe1fc52a710995571535d437f83d94ff94756a83f78e699c1ba004c38a34c01859d669fd6c64e865c23c5a7d5bf4837cfca4bef3dda + chalk: "npm:^4.0.0" + diff-sequences: "npm:^29.6.3" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/89a4a7f182590f56f526443dde69acefb1f2f0c9e59253c61d319569856c4931eae66b8a3790c443f529267a0ddba5ba80431c585deed81827032b2b2a1fc999 languageName: node linkType: hard -"jest-each@npm:30.2.0": - version: 30.2.0 - resolution: "jest-each@npm:30.2.0" +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.2.0" - chalk: "npm:^4.1.2" - jest-util: "npm:30.2.0" - pretty-format: "npm:30.2.0" - checksum: 10c0/4fa7e88a2741daaebd58cf49f9add8bd6c68657d2c106a170ebe4d7f86082c9eede2b13924304277a92e02b31b59a3c34949877da077bc27712b57913bb88321 + detect-newline: "npm:^3.0.0" + checksum: 10c0/d932a8272345cf6b6142bb70a2bb63e0856cc0093f082821577ea5bdf4643916a98744dfc992189d2b1417c38a11fa42466f6111526bc1fb81366f56410f3be9 languageName: node linkType: hard -"jest-environment-node@npm:30.2.0": - version: 30.2.0 - resolution: "jest-environment-node@npm:30.2.0" +"jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" dependencies: - "@jest/environment": "npm:30.2.0" - "@jest/fake-timers": "npm:30.2.0" - "@jest/types": "npm:30.2.0" + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + pretty-format: "npm:^29.7.0" + checksum: 10c0/f7f9a90ebee80cc688e825feceb2613627826ac41ea76a366fa58e669c3b2403d364c7c0a74d862d469b103c843154f8456d3b1c02b487509a12afa8b59edbb4 + languageName: node + linkType: hard + +"jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - jest-mock: "npm:30.2.0" - jest-util: "npm:30.2.0" - jest-validate: "npm:30.2.0" - checksum: 10c0/866ba2c04ccf003845a8ca1f372081d76923849ae8e06e50cdfed792e41a976b5f953e15f3af17ff51b111b9540cf846f7f582530ca724c2a2abf15d15a99728 + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 10c0/61f04fec077f8b1b5c1a633e3612fc0c9aa79a0ab7b05600683428f1e01a4d35346c474bde6f439f9fcc1a4aa9a2861ff852d079a43ab64b02105d1004b2592b languageName: node linkType: hard -"jest-haste-map@npm:30.2.0": - version: 30.2.0 - resolution: "jest-haste-map@npm:30.2.0" +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 10c0/552e7a97a983d3c2d4e412a44eb7de0430ff773dd99f7500962c268d6dfbfa431d7d08f919c9d960530e5f7f78eb47f267ad9b318265e5092b3ff9ede0db7c2b + languageName: node + linkType: hard + +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" dependencies: - "@jest/types": "npm:30.2.0" + "@jest/types": "npm:^29.6.3" + "@types/graceful-fs": "npm:^4.1.3" "@types/node": "npm:*" - anymatch: "npm:^3.1.3" - fb-watchman: "npm:^2.0.2" - fsevents: "npm:^2.3.3" - graceful-fs: "npm:^4.2.11" - jest-regex-util: "npm:30.0.1" - jest-util: "npm:30.2.0" - jest-worker: "npm:30.2.0" - micromatch: "npm:^4.0.8" + anymatch: "npm:^3.0.3" + fb-watchman: "npm:^2.0.0" + fsevents: "npm:^2.3.2" + graceful-fs: "npm:^4.2.9" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.4" walker: "npm:^1.0.8" dependenciesMeta: fsevents: optional: true - checksum: 10c0/61b4ad5a59b4dfadac2f903f3d723d9017aada268c49b9222ec1e15c4892fd4c36af59b65f37f026d747d829672ab9679509fea5d4248d07a93b892963e1bb4e + checksum: 10c0/2683a8f29793c75a4728787662972fedd9267704c8f7ef9d84f2beed9a977f1cf5e998c07b6f36ba5603f53cb010c911fe8cd0ac9886e073fe28ca66beefd30c languageName: node linkType: hard -"jest-leak-detector@npm:30.2.0": - version: 30.2.0 - resolution: "jest-leak-detector@npm:30.2.0" +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" dependencies: - "@jest/get-type": "npm:30.1.0" - pretty-format: "npm:30.2.0" - checksum: 10c0/68e2822aabe302983b65a08b19719a2444259af8a23ff20a6e2b6ce7759f55730f51c7cf16c65cb6be930c80a6cc70a4820239c84e8f333c9670a8e3a4a21801 + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/71bb9f77fc489acb842a5c7be030f2b9acb18574dc9fb98b3100fc57d422b1abc55f08040884bd6e6dbf455047a62f7eaff12aa4058f7cbdc11558718ca6a395 languageName: node linkType: hard @@ -22001,6 +22069,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" + dependencies: + chalk: "npm:^4.0.0" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 10c0/0d0e70b28fa5c7d4dce701dc1f46ae0922102aadc24ed45d594dd9b7ae0a8a6ef8b216718d1ab79e451291217e05d4d49a82666e1a3cc2b428b75cd9c933244e + languageName: node + linkType: hard + "jest-message-util@npm:30.2.0": version: 30.2.0 resolution: "jest-message-util@npm:30.2.0" @@ -22018,6 +22098,23 @@ __metadata: languageName: node linkType: hard +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" + dependencies: + "@babel/code-frame": "npm:^7.12.13" + "@jest/types": "npm:^29.6.3" + "@types/stack-utils": "npm:^2.0.0" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 10c0/850ae35477f59f3e6f27efac5215f706296e2104af39232bb14e5403e067992afb5c015e87a9243ec4d9df38525ef1ca663af9f2f4766aa116f127247008bd22 + languageName: node + linkType: hard + "jest-mock@npm:30.2.0": version: 30.2.0 resolution: "jest-mock@npm:30.2.0" @@ -22029,7 +22126,18 @@ __metadata: languageName: node linkType: hard -"jest-pnp-resolver@npm:^1.2.3": +"jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + jest-util: "npm:^29.7.0" + checksum: 10c0/7b9f8349ee87695a309fe15c46a74ab04c853369e5c40952d68061d9dc3159a0f0ed73e215f81b07ee97a9faaf10aebe5877a9d6255068a0977eae6a9ff1d5ac + languageName: node + linkType: hard + +"jest-pnp-resolver@npm:^1.2.2": version: 1.2.3 resolution: "jest-pnp-resolver@npm:1.2.3" peerDependencies: @@ -22048,118 +22156,124 @@ __metadata: languageName: node linkType: hard -"jest-resolve-dependencies@npm:30.2.0": - version: 30.2.0 - resolution: "jest-resolve-dependencies@npm:30.2.0" +"jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 10c0/4e33fb16c4f42111159cafe26397118dcfc4cf08bc178a67149fb05f45546a91928b820894572679d62559839d0992e21080a1527faad65daaae8743a5705a3b + languageName: node + linkType: hard + +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" dependencies: - jest-regex-util: "npm:30.0.1" - jest-snapshot: "npm:30.2.0" - checksum: 10c0/f98f2187b490f402dd9ed6b15b5d324b1220d250a5768d46b1f1582cef05b830311351532a7d19f1868a2ce0049856ae6c26587f3869995cae7850739088b879 + jest-regex-util: "npm:^29.6.3" + jest-snapshot: "npm:^29.7.0" + checksum: 10c0/b6e9ad8ae5b6049474118ea6441dfddd385b6d1fc471db0136f7c8fbcfe97137a9665e4f837a9f49f15a29a1deb95a14439b7aec812f3f99d08f228464930f0d languageName: node linkType: hard -"jest-resolve@npm:30.2.0": - version: 30.2.0 - resolution: "jest-resolve@npm:30.2.0" +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" dependencies: - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.2.0" - jest-pnp-resolver: "npm:^1.2.3" - jest-util: "npm:30.2.0" - jest-validate: "npm:30.2.0" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-pnp-resolver: "npm:^1.2.2" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + resolve: "npm:^1.20.0" + resolve.exports: "npm:^2.0.0" slash: "npm:^3.0.0" - unrs-resolver: "npm:^1.7.11" - checksum: 10c0/149576b81609a79889d08298a95d52920839f796d24f8701beacaf998a4916df205acf86b64d0bc294172a821b88d144facf44ae5a4cb3cfaa03fa06a3fc666d + checksum: 10c0/59da5c9c5b50563e959a45e09e2eace783d7f9ac0b5dcc6375dea4c0db938d2ebda97124c8161310082760e8ebbeff9f6b177c15ca2f57fb424f637a5d2adb47 languageName: node linkType: hard -"jest-runner@npm:30.2.0": - version: 30.2.0 - resolution: "jest-runner@npm:30.2.0" +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" dependencies: - "@jest/console": "npm:30.2.0" - "@jest/environment": "npm:30.2.0" - "@jest/test-result": "npm:30.2.0" - "@jest/transform": "npm:30.2.0" - "@jest/types": "npm:30.2.0" + "@jest/console": "npm:^29.7.0" + "@jest/environment": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - chalk: "npm:^4.1.2" + chalk: "npm:^4.0.0" emittery: "npm:^0.13.1" - exit-x: "npm:^0.2.2" - graceful-fs: "npm:^4.2.11" - jest-docblock: "npm:30.2.0" - jest-environment-node: "npm:30.2.0" - jest-haste-map: "npm:30.2.0" - jest-leak-detector: "npm:30.2.0" - jest-message-util: "npm:30.2.0" - jest-resolve: "npm:30.2.0" - jest-runtime: "npm:30.2.0" - jest-util: "npm:30.2.0" - jest-watcher: "npm:30.2.0" - jest-worker: "npm:30.2.0" + graceful-fs: "npm:^4.2.9" + jest-docblock: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-leak-detector: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-resolve: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" p-limit: "npm:^3.1.0" source-map-support: "npm:0.5.13" - checksum: 10c0/68cb5eb993b4a02143fc442c245b17567432709879ad5f859fec635ccdf4ad0ef128c9fc6765c1582b3f5136b36cad5c5dd173926081bfc527d490b27406383e + checksum: 10c0/2194b4531068d939f14c8d3274fe5938b77fa73126aedf9c09ec9dec57d13f22c72a3b5af01ac04f5c1cf2e28d0ac0b4a54212a61b05f10b5d6b47f2a1097bb4 languageName: node linkType: hard -"jest-runtime@npm:30.2.0": - version: 30.2.0 - resolution: "jest-runtime@npm:30.2.0" - dependencies: - "@jest/environment": "npm:30.2.0" - "@jest/fake-timers": "npm:30.2.0" - "@jest/globals": "npm:30.2.0" - "@jest/source-map": "npm:30.0.1" - "@jest/test-result": "npm:30.2.0" - "@jest/transform": "npm:30.2.0" - "@jest/types": "npm:30.2.0" +"jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/globals": "npm:^29.7.0" + "@jest/source-map": "npm:^29.6.3" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - chalk: "npm:^4.1.2" - cjs-module-lexer: "npm:^2.1.0" - collect-v8-coverage: "npm:^1.0.2" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.11" - jest-haste-map: "npm:30.2.0" - jest-message-util: "npm:30.2.0" - jest-mock: "npm:30.2.0" - jest-regex-util: "npm:30.0.1" - jest-resolve: "npm:30.2.0" - jest-snapshot: "npm:30.2.0" - jest-util: "npm:30.2.0" + chalk: "npm:^4.0.0" + cjs-module-lexer: "npm:^1.0.0" + collect-v8-coverage: "npm:^1.0.0" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" slash: "npm:^3.0.0" strip-bom: "npm:^4.0.0" - checksum: 10c0/d77b7eb75485f2b4913f635aeffa8e3e1b9baafb7a7f901f3c212195beb31f519e4b03358b5e454caee5cc94a2b9952c962fa7e5b0ff2ed06009a661924fd23e + checksum: 10c0/7cd89a1deda0bda7d0941835434e44f9d6b7bd50b5c5d9b0fc9a6c990b2d4d2cab59685ab3cb2850ed4cc37059f6de903af5a50565d7f7f1192a77d3fd6dd2a6 languageName: node linkType: hard -"jest-snapshot@npm:30.2.0": - version: 30.2.0 - resolution: "jest-snapshot@npm:30.2.0" - dependencies: - "@babel/core": "npm:^7.27.4" - "@babel/generator": "npm:^7.27.5" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - "@babel/types": "npm:^7.27.3" - "@jest/expect-utils": "npm:30.2.0" - "@jest/get-type": "npm:30.1.0" - "@jest/snapshot-utils": "npm:30.2.0" - "@jest/transform": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - babel-preset-current-node-syntax: "npm:^1.2.0" - chalk: "npm:^4.1.2" - expect: "npm:30.2.0" - graceful-fs: "npm:^4.2.11" - jest-diff: "npm:30.2.0" - jest-matcher-utils: "npm:30.2.0" - jest-message-util: "npm:30.2.0" - jest-util: "npm:30.2.0" - pretty-format: "npm:30.2.0" - semver: "npm:^7.7.2" - synckit: "npm:^0.11.8" - checksum: 10c0/961b13a3c9dcf8c533fe2ab8375bcdf441bd8680a7a7878245d8d8a4697432d806f7817cfaa061904e0c6cc939a38f1fe9f5af868b86328e77833a58822b3b63 +"jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" + dependencies: + "@babel/core": "npm:^7.11.6" + "@babel/generator": "npm:^7.7.2" + "@babel/plugin-syntax-jsx": "npm:^7.7.2" + "@babel/plugin-syntax-typescript": "npm:^7.7.2" + "@babel/types": "npm:^7.3.3" + "@jest/expect-utils": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-preset-current-node-syntax: "npm:^1.0.0" + chalk: "npm:^4.0.0" + expect: "npm:^29.7.0" + graceful-fs: "npm:^4.2.9" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + natural-compare: "npm:^1.4.0" + pretty-format: "npm:^29.7.0" + semver: "npm:^7.5.3" + checksum: 10c0/6e9003c94ec58172b4a62864a91c0146513207bedf4e0a06e1e2ac70a4484088a2683e3a0538d8ea913bcfd53dc54a9b98a98cdfa562e7fe1d1339aeae1da570 languageName: node linkType: hard @@ -22177,7 +22291,7 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.0.0": +"jest-util@npm:^29.0.0, jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" dependencies: @@ -22191,76 +22305,75 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:30.2.0": - version: 30.2.0 - resolution: "jest-validate@npm:30.2.0" +"jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" dependencies: - "@jest/get-type": "npm:30.1.0" - "@jest/types": "npm:30.2.0" - camelcase: "npm:^6.3.0" - chalk: "npm:^4.1.2" + "@jest/types": "npm:^29.6.3" + camelcase: "npm:^6.2.0" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^29.6.3" leven: "npm:^3.1.0" - pretty-format: "npm:30.2.0" - checksum: 10c0/56566643d79ca07f021fa14cebb62c423ae405757cb8d742113ff0070f0761b80c77f665fac8d89622faaab71fc5452e1471939028187a88c8445303d7976255 + pretty-format: "npm:^29.7.0" + checksum: 10c0/a20b930480c1ed68778c739f4739dce39423131bc070cd2505ddede762a5570a256212e9c2401b7ae9ba4d7b7c0803f03c5b8f1561c62348213aba18d9dbece2 languageName: node linkType: hard -"jest-watcher@npm:30.2.0": - version: 30.2.0 - resolution: "jest-watcher@npm:30.2.0" +"jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" dependencies: - "@jest/test-result": "npm:30.2.0" - "@jest/types": "npm:30.2.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" emittery: "npm:^0.13.1" - jest-util: "npm:30.2.0" - string-length: "npm:^4.0.2" - checksum: 10c0/51587968fabb5b180383d638a04db253b82d9cc3f53fbba06ba7b0544146178d50becc090aca7931e2d4eb9aa1624bb3fbd1a2571484c9391554404e8b5d8fe7 + jest-util: "npm:^29.7.0" + string-length: "npm:^4.0.1" + checksum: 10c0/ec6c75030562fc8f8c727cb8f3b94e75d831fc718785abfc196e1f2a2ebc9a2e38744a15147170039628a853d77a3b695561ce850375ede3a4ee6037a2574567 languageName: node linkType: hard -"jest-worker@npm:30.2.0": - version: 30.2.0 - resolution: "jest-worker@npm:30.2.0" +"jest-worker@npm:^27.4.5": + version: 27.5.1 + resolution: "jest-worker@npm:27.5.1" dependencies: "@types/node": "npm:*" - "@ungap/structured-clone": "npm:^1.3.0" - jest-util: "npm:30.2.0" merge-stream: "npm:^2.0.0" - supports-color: "npm:^8.1.1" - checksum: 10c0/1ea47f6c682ba6cdbd50630544236aabccacf1d88335607206c10871a9777a45b0fc6336c8eb6344e32e69dd7681de17b2199b4d4552b00d48aade303627125c + supports-color: "npm:^8.0.0" + checksum: 10c0/8c4737ffd03887b3c6768e4cc3ca0269c0336c1e4b1b120943958ddb035ed2a0fc6acab6dc99631720a3720af4e708ff84fb45382ad1e83c27946adf3623969b languageName: node linkType: hard -"jest-worker@npm:^27.4.5": - version: 27.5.1 - resolution: "jest-worker@npm:27.5.1" +"jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" dependencies: "@types/node": "npm:*" + jest-util: "npm:^29.7.0" merge-stream: "npm:^2.0.0" supports-color: "npm:^8.0.0" - checksum: 10c0/8c4737ffd03887b3c6768e4cc3ca0269c0336c1e4b1b120943958ddb035ed2a0fc6acab6dc99631720a3720af4e708ff84fb45382ad1e83c27946adf3623969b + checksum: 10c0/5570a3a005b16f46c131968b8a5b56d291f9bbb85ff4217e31c80bd8a02e7de799e59a54b95ca28d5c302f248b54cbffde2d177c2f0f52ffcee7504c6eabf660 languageName: node linkType: hard -"jest@npm:30.2.0, jest@npm:^30.2.0": - version: 30.2.0 - resolution: "jest@npm:30.2.0" +"jest@npm:^29.7.0": + version: 29.7.0 + resolution: "jest@npm:29.7.0" dependencies: - "@jest/core": "npm:30.2.0" - "@jest/types": "npm:30.2.0" - import-local: "npm:^3.2.0" - jest-cli: "npm:30.2.0" + "@jest/core": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + import-local: "npm:^3.0.2" + jest-cli: "npm:^29.7.0" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true bin: - jest: ./bin/jest.js - checksum: 10c0/af580c6e265d21870c2c98e31f17f2f5cb5c9e6cf9be26b95eaf4fad4140a01579f3b5844d4264cd8357eb24908e95f983ea84d20b8afef46e62aed3dd9452eb + jest: bin/jest.js + checksum: 10c0/f40eb8171cf147c617cc6ada49d062fbb03b4da666cb8d39cdbfb739a7d75eea4c3ca150fb072d0d273dce0c753db4d0467d54906ad0293f59c54f9db4a09d8b languageName: node linkType: hard @@ -23574,7 +23687,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -25737,7 +25850,7 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.7": +"pirates@npm:^4.0.4": version: 4.0.7 resolution: "pirates@npm:4.0.7" checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a @@ -26032,6 +26145,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": "npm:^29.6.3" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^18.0.0" + checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f + languageName: node + linkType: hard + "proc-log@npm:^4.0.0, proc-log@npm:^4.2.0": version: 4.2.0 resolution: "proc-log@npm:4.2.0" @@ -26098,7 +26222,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.4.2": +"prompts@npm:^2.0.1, prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -26267,10 +26391,10 @@ __metadata: languageName: node linkType: hard -"pure-rand@npm:^7.0.0": - version: 7.0.1 - resolution: "pure-rand@npm:7.0.1" - checksum: 10c0/9cade41030f5ec95f5d55a11a71404cd6f46b69becaad892097cd7f58e2c6248cd0a933349ca7d21336ab629f1da42ffe899699b671bc4651600eaf6e57f837e +"pure-rand@npm:^6.0.0": + version: 6.1.0 + resolution: "pure-rand@npm:6.1.0" + checksum: 10c0/1abe217897bf74dcb3a0c9aba3555fe975023147b48db540aa2faf507aee91c03bf54f6aef0eb2bf59cc259a16d06b28eca37f0dc426d94f4692aeff02fb0e65 languageName: node linkType: hard @@ -26519,7 +26643,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.3.1": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 @@ -27062,6 +27186,13 @@ __metadata: languageName: node linkType: hard +"resolve.exports@npm:^2.0.0": + version: 2.0.3 + resolution: "resolve.exports@npm:2.0.3" + checksum: 10c0/1ade1493f4642a6267d0a5e68faeac20b3d220f18c28b140343feb83694d8fed7a286852aef43689d16042c61e2ddb270be6578ad4a13990769e12065191200d + languageName: node + linkType: hard + "resolve@npm:1.1.x": version: 1.1.7 resolution: "resolve@npm:1.1.7" @@ -27078,7 +27209,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.22.10, resolve@npm:^1.22.4": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.10, resolve@npm:^1.22.4": version: 1.22.11 resolution: "resolve@npm:1.22.11" dependencies: @@ -27130,7 +27261,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.10#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.10#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": version: 1.22.11 resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" dependencies: @@ -27662,7 +27793,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.2, semver@npm:^7.7.3": +"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -27959,7 +28090,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3": +"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 @@ -28380,7 +28511,7 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.6": +"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -28541,7 +28672,7 @@ __metadata: languageName: node linkType: hard -"string-length@npm:^4.0.2": +"string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" dependencies: @@ -28977,7 +29108,7 @@ __metadata: languageName: node linkType: hard -"synckit@npm:0.11.11, synckit@npm:^0.11.7, synckit@npm:^0.11.8": +"synckit@npm:0.11.11, synckit@npm:^0.11.7": version: 0.11.11 resolution: "synckit@npm:0.11.11" dependencies: @@ -31673,13 +31804,13 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" +"write-file-atomic@npm:^4.0.2": + version: 4.0.2 + resolution: "write-file-atomic@npm:4.0.2" dependencies: imurmurhash: "npm:^0.1.4" - signal-exit: "npm:^4.0.1" - checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d + signal-exit: "npm:^3.0.7" + checksum: 10c0/a2c282c95ef5d8e1c27b335ae897b5eca00e85590d92a3fd69a437919b7b93ff36a69ea04145da55829d2164e724bc62202cdb5f4b208b425aba0807889375c7 languageName: node linkType: hard @@ -31912,7 +32043,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.3.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: From 91c1aafee1cb72fbc2f4ea0b305767c17a93eeed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 14:37:20 +0100 Subject: [PATCH 08/21] chore(deps): bump @nestjs/throttler from 6.4.0 to 6.5.0 (#3707) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/apps/job-launcher/server/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index a9e88d937c..f462adffdd 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -43,7 +43,7 @@ "@nestjs/schedule": "^4.0.1", "@nestjs/swagger": "^7.4.2", "@nestjs/terminus": "^11.0.0", - "@nestjs/throttler": "^6.4.0", + "@nestjs/throttler": "^6.5.0", "@nestjs/typeorm": "^10.0.1", "@sendgrid/mail": "^8.1.3", "@types/passport-jwt": "^4.0.1", diff --git a/yarn.lock b/yarn.lock index f9e60501bf..09d8305a27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -609,7 +609,7 @@ __metadata: "@nestjs/swagger": "npm:^7.4.2" "@nestjs/terminus": "npm:^11.0.0" "@nestjs/testing": "npm:^10.4.6" - "@nestjs/throttler": "npm:^6.4.0" + "@nestjs/throttler": "npm:^6.5.0" "@nestjs/typeorm": "npm:^10.0.1" "@sendgrid/mail": "npm:^8.1.3" "@types/bcrypt": "npm:^5.0.2" @@ -7123,14 +7123,14 @@ __metadata: languageName: node linkType: hard -"@nestjs/throttler@npm:^6.4.0": - version: 6.4.0 - resolution: "@nestjs/throttler@npm:6.4.0" +"@nestjs/throttler@npm:^6.5.0": + version: 6.5.0 + resolution: "@nestjs/throttler@npm:6.5.0" peerDependencies: "@nestjs/common": ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 "@nestjs/core": ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 reflect-metadata: ^0.1.13 || ^0.2.0 - checksum: 10c0/796134644e341aad4a403b7431524db97adc31ae8771fc1160a4694a24c295b7a3dd15abcb72b9ea3a0702247b929f501fc5dc74a3f30d915f2667a39ba5c5d7 + checksum: 10c0/bd755e765d020189b24fd8cb8a5989b47d7856abdc8efc881d73dd76e71b8e6e4466e532464434fd1199a106bf4752bda3d0036ef4aa13aa61e9317f60658da8 languageName: node linkType: hard From 45f5f3d118703db544b97ab37e371dd59bfbbe87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Tue, 16 Dec 2025 16:49:48 +0100 Subject: [PATCH 09/21] [Subgraph] Fix internal transaction handling when there is more than one main method (#3713) Co-authored-by: portuu3 --- .changeset/tasty-groups-sing.md | 6 ++++ .../human_protocol_sdk/constants.py | 12 +++---- .../human-protocol-sdk/src/constants.ts | 12 +++---- .../subgraph/src/mapping/utils/transaction.ts | 36 +++++++++++++------ 4 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 .changeset/tasty-groups-sing.md diff --git a/.changeset/tasty-groups-sing.md b/.changeset/tasty-groups-sing.md new file mode 100644 index 0000000000..e28a428f67 --- /dev/null +++ b/.changeset/tasty-groups-sing.md @@ -0,0 +1,6 @@ +--- +"@human-protocol/sdk": patch +"@human-protocol/python-sdk": patch +--- + +Subgraph fix - Fix internal transaction handling when there is more than one main method event in the same transaction. diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py index b02169384d..4c0abcf005 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py @@ -37,7 +37,7 @@ class OperatorCategory(Enum): "https://api.studio.thegraph.com/query/74256/ethereum/version/latest" ), "subgraph_url_api_key": ( - "https://gateway.thegraph.com/api/deployments/id/QmXGmcjEtwwEgB83KE2ECjjYY38kLMqzaq4ip8GWY7A6zz" + "https://gateway.thegraph.com/api/deployments/id/QmeCB3KX49nRAkzgqancc3yL3VMJvt65YtL1zrLCFgr2n5" ), "hmt_address": "0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867", "factory_address": "0xD9c75a1Aa4237BB72a41E5E26bd8384f10c1f55a", @@ -53,7 +53,7 @@ class OperatorCategory(Enum): "https://api.studio.thegraph.com/query/74256/sepolia/version/latest" ), "subgraph_url_api_key": ( - "https://gateway.thegraph.com/api/deployments/id/QmT4xNvZh8ymarrk1zdytjLhCW59iuTavsd4JgHS4LbCVB" + "https://gateway.thegraph.com/api/deployments/id/QmcMntqZSTh8wJddxgp2hYcdw78wZFU86LHTHzJ1bTVUDc" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0x5987A5558d961ee674efe4A8c8eB7B1b5495D3bf", @@ -69,7 +69,7 @@ class OperatorCategory(Enum): "https://api.studio.thegraph.com/query/74256/bsc/version/latest" ), "subgraph_url_api_key": ( - "https://gateway.thegraph.com/api/deployments/id/QmdVdpm9NnFz5B8QyzhW1bW1nNfRWemTiFn2MrhYZGTSQD" + "https://gateway.thegraph.com/api/deployments/id/QmRexbu8eLZ1iE7ZLMtKxAr9GJnQ1JVrXhybKq6JkJ9XLE" ), "hmt_address": "0x711Fd6ab6d65A98904522d4e3586F492B989c527", "factory_address": "0x92FD968AcBd521c232f5fB8c33b342923cC72714", @@ -85,7 +85,7 @@ class OperatorCategory(Enum): "https://api.studio.thegraph.com/query/74256/bsc-testnet/version/latest" ), "subgraph_url_api_key": ( - "https://gateway.thegraph.com/api/deployments/id/QmZjYMktZe8RAz7W7qL33VZBV6AC57xsLyE1cEfv6NABdZ" + "https://gateway.thegraph.com/api/deployments/id/QmfFBXsAP7nbckFx34XYcNq2hRnfoVNrfqCvuk7hmAtYJT" ), "hmt_address": "0xE3D74BBFa45B4bCa69FF28891fBE392f4B4d4e4d", "factory_address": "0x2bfA592DBDaF434DDcbb893B1916120d181DAD18", @@ -103,7 +103,7 @@ class OperatorCategory(Enum): "https://api.studio.thegraph.com/query/74256/polygon/version/latest" ), "subgraph_url_api_key": ( - "https://gateway.thegraph.com/api/deployments/id/QmUt9mmfNjtC5ZnQNiWHRbFG3k5zfngMuoTyky9jhXYqG2" + "https://gateway.thegraph.com/api/deployments/id/QmUwHMDjnDHDB5cowGqd96SRJ1sZegoAPanjxBWUyLZghv" ), "hmt_address": "0xc748B2A084F8eFc47E086ccdDD9b7e67aEb571BF", "factory_address": "0xBDBfD2cC708199C5640C6ECdf3B0F4A4C67AdfcB", @@ -121,7 +121,7 @@ class OperatorCategory(Enum): "https://api.studio.thegraph.com/query/74256/amoy/version/latest" ), "subgraph_url_api_key": ( - "https://gateway.thegraph.com/api/deployments/id/QmWRUFWpWoRRUh7Ec1HUJEwxc84DkP4iFTfLLsoVngJAPa" + "https://gateway.thegraph.com/api/deployments/id/QmTJfcvVVmw8fe5CwRP6tZD5FzE2ESrm3ryygS1YZMYhM7" ), "hmt_address": "0x792abbcC99c01dbDec49c9fa9A828a186Da45C33", "factory_address": "0xAFf5a986A530ff839d49325A5dF69F96627E8D29", diff --git a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts index 1b4c19c402..adc9d298d5 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/constants.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/constants.ts @@ -36,7 +36,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/ethereum/version/latest', subgraphUrlApiKey: - 'https://gateway.thegraph.com/api/deployments/id/QmXGmcjEtwwEgB83KE2ECjjYY38kLMqzaq4ip8GWY7A6zz', + 'https://gateway.thegraph.com/api/deployments/id/QmeCB3KX49nRAkzgqancc3yL3VMJvt65YtL1zrLCFgr2n5', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -51,7 +51,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/sepolia/version/latest', subgraphUrlApiKey: - 'https://gateway.thegraph.com/api/deployments/id/QmT4xNvZh8ymarrk1zdytjLhCW59iuTavsd4JgHS4LbCVB', + 'https://gateway.thegraph.com/api/deployments/id/QmcMntqZSTh8wJddxgp2hYcdw78wZFU86LHTHzJ1bTVUDc', oldSubgraphUrl: '', oldFactoryAddress: '', }, @@ -66,7 +66,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/bsc/version/latest', subgraphUrlApiKey: - 'https://gateway.thegraph.com/api/deployments/id/QmdVdpm9NnFz5B8QyzhW1bW1nNfRWemTiFn2MrhYZGTSQD', + 'https://gateway.thegraph.com/api/deployments/id/QmRexbu8eLZ1iE7ZLMtKxAr9GJnQ1JVrXhybKq6JkJ9XLE', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/bsc', oldFactoryAddress: '0xc88bC422cAAb2ac8812de03176402dbcA09533f4', }, @@ -81,7 +81,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/bsc-testnet/version/latest', subgraphUrlApiKey: - 'https://gateway.thegraph.com/api/deployments/id/QmZjYMktZe8RAz7W7qL33VZBV6AC57xsLyE1cEfv6NABdZ', + 'https://gateway.thegraph.com/api/deployments/id/QmfFBXsAP7nbckFx34XYcNq2hRnfoVNrfqCvuk7hmAtYJT', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/bsctest', oldFactoryAddress: '0xaae6a2646c1f88763e62e0cd08ad050ea66ac46f', @@ -97,7 +97,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/polygon/version/latest', subgraphUrlApiKey: - 'https://gateway.thegraph.com/api/deployments/id/QmUt9mmfNjtC5ZnQNiWHRbFG3k5zfngMuoTyky9jhXYqG2', + 'https://gateway.thegraph.com/api/deployments/id/QmUwHMDjnDHDB5cowGqd96SRJ1sZegoAPanjxBWUyLZghv', oldSubgraphUrl: 'https://api.thegraph.com/subgraphs/name/humanprotocol/polygon', oldFactoryAddress: '0x45eBc3eAE6DA485097054ae10BA1A0f8e8c7f794', @@ -113,7 +113,7 @@ export const NETWORKS: { subgraphUrl: 'https://api.studio.thegraph.com/query/74256/amoy/version/latest', subgraphUrlApiKey: - 'https://gateway.thegraph.com/api/deployments/id/QmWRUFWpWoRRUh7Ec1HUJEwxc84DkP4iFTfLLsoVngJAPa', + 'https://gateway.thegraph.com/api/deployments/id/QmTJfcvVVmw8fe5CwRP6tZD5FzE2ESrm3ryygS1YZMYhM7', oldSubgraphUrl: '', oldFactoryAddress: '', }, diff --git a/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts b/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts index 7ede1ffc5a..65eb1ed009 100644 --- a/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts +++ b/packages/sdk/typescript/subgraph/src/mapping/utils/transaction.ts @@ -5,12 +5,13 @@ import { toEventId, toPreviousEventId } from './event'; const mainMethods: string[] = [ 'createEscrow', 'setup', - 'fund', - 'bulkTransfer', - 'storeResults', - 'withdraw', 'requestCancellation', + 'withdraw', + 'fund', 'cancel', + 'complete', + 'storeResults', + 'bulkTransfer', 'stake', 'unstake', 'slash', @@ -71,13 +72,26 @@ export function createTransaction( mainMethods.includes(method) && Address.fromBytes(transaction.to) == to ) { - transaction.method = method; - transaction.from = from; - transaction.value = value !== null ? value : BigInt.fromI32(0); - transaction.token = token; - transaction.escrow = escrow; - transaction.receiver = receiver; - transaction.save(); + if (mainMethods.includes(transaction.method)) { + const internalTransaction = new InternalTransaction(toEventId(event)); + internalTransaction.method = method; + internalTransaction.from = from; + internalTransaction.to = to; + internalTransaction.value = value !== null ? value : BigInt.fromI32(0); + internalTransaction.transaction = transaction.txHash; + internalTransaction.token = token; + internalTransaction.escrow = escrow; + internalTransaction.receiver = receiver; + internalTransaction.save(); + } else { + transaction.method = method; + transaction.from = from; + transaction.value = value !== null ? value : BigInt.fromI32(0); + transaction.token = token; + transaction.escrow = escrow; + transaction.receiver = receiver; + transaction.save(); + } } else { if ( transaction.method == 'set' && From 5cff718a7c977487130f5bb0ef0ece30f2fae6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:06:05 +0100 Subject: [PATCH 10/21] [SDK][Typescript] Fix operator reputation networks (#3723) --- .changeset/hot-animals-trade.md | 5 +++++ .../human-protocol-sdk/src/graphql/queries/operator.ts | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .changeset/hot-animals-trade.md diff --git a/.changeset/hot-animals-trade.md b/.changeset/hot-animals-trade.md new file mode 100644 index 0000000000..b8f7b316c1 --- /dev/null +++ b/.changeset/hot-animals-trade.md @@ -0,0 +1,5 @@ +--- +"@human-protocol/sdk": patch +--- + +Update LEADER_FRAGMENT to include address field in reputationNetworks diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts index 0a81b2cbf5..e2f4327710 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/operator.ts @@ -15,7 +15,9 @@ const LEADER_FRAGMENT = gql` jobTypes registrationNeeded registrationInstructions - reputationNetworks + reputationNetworks { + address + } name category staker { From fd58b3c5ce2c990319bf9ce5c942c477b73c7097 Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Thu, 18 Dec 2025 19:03:28 +0300 Subject: [PATCH 11/21] refactor: dashboard chains usage and HUMAN App errors (#3722) --- .../searchResults/api/useKvStoreData.ts | 2 +- packages/apps/dashboard/server/.env.example | 1 - packages/apps/dashboard/server/package.json | 3 +- .../common/config/network-config.service.ts | 42 +++++++------------ .../server/src/common/constants/chains.ts | 28 +++++++++++++ .../server/src/common/constants/index.ts | 2 + .../dashboard/server/src/common/enums/web3.ts | 5 --- .../server/src/common/utils/constants.ts | 14 ------- .../server/src/common/utils/environment.ts | 4 ++ .../server/src/common/validators/index.ts | 1 + .../server/src/common/validators/web3.ts | 12 ++++++ .../src/modules/details/details.controller.ts | 10 ++--- .../src/modules/details/details.service.ts | 10 ++--- .../src/modules/details/details.spec.ts | 17 ++++---- .../src/modules/details/dto/common.dto.ts | 9 ++++ .../details/dto/details-pagination.dto.ts | 29 +++---------- .../details/dto/details-response.dto.ts | 4 +- .../src/modules/details/dto/escrow.dto.ts | 10 ++--- .../src/modules/details/dto/operator.dto.ts | 13 +++--- .../src/modules/details/dto/wallet.dto.ts | 7 ++-- .../modules/networks/networks.controller.ts | 2 +- ...rvice.spec.ts => networks.service.spec.ts} | 34 ++++++++------- .../src/modules/networks/networks.service.ts | 3 +- .../integrations/kv-store/kv-store.gateway.ts | 23 ++++++---- .../server/src/common/guards/jwt.auth.ts | 7 +++- .../server/src/logger/__mocks__/index.ts | 11 +++++ .../modules/cron-job/cron-job.service.spec.ts | 13 +++--- .../src/modules/cron-job/cron-job.service.ts | 5 ++- .../src/modules/web3/web3.controller.ts | 5 +-- .../server/src/modules/web3/web3.dto.ts | 23 +++++++--- .../server/src/common/validators/index.ts | 12 ++++-- 31 files changed, 209 insertions(+), 152 deletions(-) create mode 100644 packages/apps/dashboard/server/src/common/constants/chains.ts create mode 100644 packages/apps/dashboard/server/src/common/constants/index.ts delete mode 100644 packages/apps/dashboard/server/src/common/enums/web3.ts delete mode 100644 packages/apps/dashboard/server/src/common/utils/constants.ts create mode 100644 packages/apps/dashboard/server/src/common/validators/index.ts create mode 100644 packages/apps/dashboard/server/src/common/validators/web3.ts create mode 100644 packages/apps/dashboard/server/src/modules/details/dto/common.dto.ts rename packages/apps/dashboard/server/src/modules/networks/{network.service.spec.ts => networks.service.spec.ts} (87%) create mode 100644 packages/apps/job-launcher/server/src/logger/__mocks__/index.ts diff --git a/packages/apps/dashboard/client/src/features/searchResults/api/useKvStoreData.ts b/packages/apps/dashboard/client/src/features/searchResults/api/useKvStoreData.ts index 056bb530ee..6eff8d0fea 100644 --- a/packages/apps/dashboard/client/src/features/searchResults/api/useKvStoreData.ts +++ b/packages/apps/dashboard/client/src/features/searchResults/api/useKvStoreData.ts @@ -12,7 +12,7 @@ const useKvstoreData = (chainId: number, address: string) => { queryFn: async () => { const { data } = await httpClient.get( `${apiPaths.kvstore.path}/${address}`, - { params: { chain_id: chainId || -1 } } + { params: { chainId: chainId || -1 } } ); const validResponse = validateResponse(data, kvstoreDataSchema); diff --git a/packages/apps/dashboard/server/.env.example b/packages/apps/dashboard/server/.env.example index 30998286a8..c42912b7b2 100644 --- a/packages/apps/dashboard/server/.env.example +++ b/packages/apps/dashboard/server/.env.example @@ -22,7 +22,6 @@ S3_BUCKET=dashboard-hcaptcha-historical-stats S3_USE_SSL=false # Web3 -WEB3_ENV=testnet RPC_URL_POLYGON=https://rpc-amoy.polygon.technology RPC_URL_BSC_TESTNET=https://bsc-testnet.drpc.org RPC_URL_SEPOLIA=https://rpc.sepolia.org diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 3db3938026..2dadd9282a 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -17,7 +17,8 @@ "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand" + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "typecheck": "tsc --noEmit" }, "dependencies": { "@human-protocol/core": "workspace:*", diff --git a/packages/apps/dashboard/server/src/common/config/network-config.service.ts b/packages/apps/dashboard/server/src/common/config/network-config.service.ts index 82805f0fb8..2741a66590 100644 --- a/packages/apps/dashboard/server/src/common/config/network-config.service.ts +++ b/packages/apps/dashboard/server/src/common/config/network-config.service.ts @@ -1,18 +1,18 @@ -import { ChainId } from '@human-protocol/sdk'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { Web3Env } from '../enums/web3'; + import { - LOCALHOST_CHAIN_IDS, - MAINNET_CHAIN_IDS, - TESTNET_CHAIN_IDS, -} from '../utils/constants'; + DevelopmentChainId, + ProductionChainId, + ChainIds, + type ChainId, +} from '../constants'; export interface TokensList { [key: string]: string | undefined; } export interface NetworkDto { - chainId: number; + chainId: ChainId; rpcUrl?: string; } @@ -28,65 +28,53 @@ export class NetworkConfigService { this.networkMap = { ...(this.configService.get('RPC_URL_ETHEREUM') && { ethereum: { - chainId: ChainId.MAINNET, + chainId: ProductionChainId.ETHEREUM, rpcUrl: this.configService.get('RPC_URL_ETHEREUM'), }, }), ...(this.configService.get('RPC_URL_SEPOLIA') && { sepolia: { - chainId: ChainId.SEPOLIA, + chainId: DevelopmentChainId.SEPOLIA, rpcUrl: this.configService.get('RPC_URL_SEPOLIA'), }, }), ...(this.configService.get('RPC_URL_POLYGON') && { polygon: { - chainId: ChainId.POLYGON, + chainId: ProductionChainId.POLYGON_MAINNET, rpcUrl: this.configService.get('RPC_URL_POLYGON'), }, }), ...(this.configService.get('RPC_URL_POLYGON_AMOY') && { amoy: { - chainId: ChainId.POLYGON_AMOY, + chainId: DevelopmentChainId.POLYGON_AMOY, rpcUrl: this.configService.get('RPC_URL_POLYGON_AMOY'), }, }), ...(this.configService.get('RPC_URL_BSC_MAINNET') && { bsc: { - chainId: ChainId.BSC_MAINNET, + chainId: ProductionChainId.BSC_MAINNET, rpcUrl: this.configService.get('RPC_URL_BSC_MAINNET'), }, }), ...(this.configService.get('RPC_URL_BSC_TESTNET') && { bsctest: { - chainId: ChainId.BSC_TESTNET, + chainId: DevelopmentChainId.BSC_TESTNET, rpcUrl: this.configService.get('RPC_URL_BSC_TESTNET'), }, }), ...(this.configService.get('RPC_URL_LOCALHOST') && { localhost: { - chainId: ChainId.LOCALHOST, + chainId: DevelopmentChainId.LOCALHOST, rpcUrl: this.configService.get('RPC_URL_LOCALHOST'), }, }), }; - const validChainIds = (() => { - switch (this.configService.get('WEB3_ENV')) { - case Web3Env.MAINNET: - return MAINNET_CHAIN_IDS; - case Web3Env.LOCALHOST: - return LOCALHOST_CHAIN_IDS; - default: - return TESTNET_CHAIN_IDS; - } - })(); // Remove networks without RPC URLs this.networkMap = Object.keys(this.networkMap) .filter((network) => { const networkConfig = this.networkMap[network]; - return ( - networkConfig.rpcUrl && validChainIds.includes(networkConfig.chainId) - ); + return networkConfig.rpcUrl && ChainIds.includes(networkConfig.chainId); }) .reduce((newNetworkMap: NetworkMapDto, network) => { newNetworkMap[network] = this.networkMap[network]; diff --git a/packages/apps/dashboard/server/src/common/constants/chains.ts b/packages/apps/dashboard/server/src/common/constants/chains.ts new file mode 100644 index 0000000000..74043bf6bc --- /dev/null +++ b/packages/apps/dashboard/server/src/common/constants/chains.ts @@ -0,0 +1,28 @@ +import { ChainId as SdkChainId } from '@human-protocol/sdk'; + +import Environment from '../utils/environment'; + +export const ProductionChainId = { + POLYGON_MAINNET: SdkChainId.POLYGON, + BSC_MAINNET: SdkChainId.BSC_MAINNET, + ETHEREUM: SdkChainId.MAINNET, +} as const satisfies Record; + +type ProductionChainId = + (typeof ProductionChainId)[keyof typeof ProductionChainId]; + +export const DevelopmentChainId = { + POLYGON_AMOY: SdkChainId.POLYGON_AMOY, + BSC_TESTNET: SdkChainId.BSC_TESTNET, + SEPOLIA: SdkChainId.SEPOLIA, + LOCALHOST: SdkChainId.LOCALHOST, +} as const satisfies Record; + +type DevelopmentChainId = + (typeof DevelopmentChainId)[keyof typeof DevelopmentChainId]; + +export const ChainIds = Object.values( + Environment.isProduction() ? ProductionChainId : DevelopmentChainId, +).filter((value): value is ChainId => typeof value === 'number'); + +export type ChainId = ProductionChainId | DevelopmentChainId; diff --git a/packages/apps/dashboard/server/src/common/constants/index.ts b/packages/apps/dashboard/server/src/common/constants/index.ts new file mode 100644 index 0000000000..dffd59c532 --- /dev/null +++ b/packages/apps/dashboard/server/src/common/constants/index.ts @@ -0,0 +1,2 @@ +export * from './chains'; +export * from './operator'; diff --git a/packages/apps/dashboard/server/src/common/enums/web3.ts b/packages/apps/dashboard/server/src/common/enums/web3.ts deleted file mode 100644 index 76c95fb5a4..0000000000 --- a/packages/apps/dashboard/server/src/common/enums/web3.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum Web3Env { - TESTNET = 'testnet', - MAINNET = 'mainnet', - LOCALHOST = 'localhost', -} diff --git a/packages/apps/dashboard/server/src/common/utils/constants.ts b/packages/apps/dashboard/server/src/common/utils/constants.ts deleted file mode 100644 index 71594d0819..0000000000 --- a/packages/apps/dashboard/server/src/common/utils/constants.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ChainId } from '@human-protocol/sdk'; - -export const LOCALHOST_CHAIN_IDS = [ChainId.LOCALHOST]; - -export const TESTNET_CHAIN_IDS = [ - ChainId.BSC_TESTNET, - ChainId.POLYGON_AMOY, - ChainId.SEPOLIA, -]; -export const MAINNET_CHAIN_IDS = [ - ChainId.MAINNET, - ChainId.BSC_MAINNET, - ChainId.POLYGON, -]; diff --git a/packages/apps/dashboard/server/src/common/utils/environment.ts b/packages/apps/dashboard/server/src/common/utils/environment.ts index b85af194f0..cce705afa6 100644 --- a/packages/apps/dashboard/server/src/common/utils/environment.ts +++ b/packages/apps/dashboard/server/src/common/utils/environment.ts @@ -20,6 +20,10 @@ class Environment { ].includes(Environment.name as EnvironmentName); } + static isProduction(): boolean { + return Environment.name === EnvironmentName.PRODUCTION; + } + static isTest(): boolean { return Environment.name === EnvironmentName.TEST; } diff --git a/packages/apps/dashboard/server/src/common/validators/index.ts b/packages/apps/dashboard/server/src/common/validators/index.ts new file mode 100644 index 0000000000..db72d289ce --- /dev/null +++ b/packages/apps/dashboard/server/src/common/validators/index.ts @@ -0,0 +1 @@ +export * from './web3'; diff --git a/packages/apps/dashboard/server/src/common/validators/web3.ts b/packages/apps/dashboard/server/src/common/validators/web3.ts new file mode 100644 index 0000000000..e21e40472f --- /dev/null +++ b/packages/apps/dashboard/server/src/common/validators/web3.ts @@ -0,0 +1,12 @@ +import { applyDecorators } from '@nestjs/common'; +import { Transform } from 'class-transformer'; +import { IsIn } from 'class-validator'; + +import { ChainIds } from '../constants'; + +export function IsChainId() { + return applyDecorators( + IsIn(ChainIds), + Transform(({ value }) => Number(value)), + ); +} diff --git a/packages/apps/dashboard/server/src/modules/details/details.controller.ts b/packages/apps/dashboard/server/src/modules/details/details.controller.ts index af22967f04..6d703994ea 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.controller.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.controller.ts @@ -1,4 +1,4 @@ -import { ApiOperation, ApiResponse, ApiTags, ApiQuery } from '@nestjs/swagger'; +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { Controller, Get, @@ -8,7 +8,6 @@ import { UsePipes, ValidationPipe, } from '@nestjs/common'; -import { ChainId } from '@human-protocol/sdk'; import { AddressValidationPipe } from '../../common/pipes/address-validation.pipe'; import { DetailsService } from './details.service'; @@ -26,6 +25,7 @@ import { WalletDto } from './dto/wallet.dto'; import { EscrowDto, EscrowPaginationDto } from './dto/escrow.dto'; import { OperatorDto } from './dto/operator.dto'; import { TransactionPaginationDto } from './dto/transaction.dto'; +import { ChainIdQueryDto } from './dto/common.dto'; @ApiTags('Details') @Controller('/details') @@ -56,7 +56,6 @@ export class DetailsController { } @Get('/:address') - @ApiQuery({ name: 'chainId', enum: ChainId }) @HttpCode(200) @ApiOperation({ summary: 'Get address details', @@ -69,7 +68,7 @@ export class DetailsController { }) async details( @Param('address', AddressValidationPipe) address: string, - @Query('chainId') chainId: ChainId, + @Query() { chainId }: ChainIdQueryDto, ): Promise { const details: WalletDto | EscrowDto | OperatorDto = await this.detailsService.getDetails(chainId, address); @@ -167,7 +166,6 @@ export class DetailsController { summary: 'Get KVStore data by address', description: 'Returns all the data stored in KVStore for a given address.', }) - @ApiQuery({ name: 'chain_id', enum: ChainId, required: true }) @ApiResponse({ status: 200, description: 'Data retrieved successfully', @@ -176,7 +174,7 @@ export class DetailsController { }) async KVStore( @Param('address', AddressValidationPipe) address: string, - @Query('chain_id') chainId: ChainId, + @Query() { chainId }: ChainIdQueryDto, ): Promise { return this.detailsService.getKVStoreData(chainId, address); } diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index 1982a272a8..63905022ea 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -1,5 +1,5 @@ +import { HMToken__factory } from '@human-protocol/core/typechain-types'; import { - ChainId, EscrowUtils, IEscrowsFilter, IOperatorsFilter, @@ -12,14 +12,13 @@ import { TransactionUtils, WorkerUtils, } from '@human-protocol/sdk'; +import { HttpService } from '@nestjs/axios'; import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { plainToInstance } from 'class-transformer'; - -import { HMToken__factory } from '@human-protocol/core/typechain-types'; -import { HttpService } from '@nestjs/axios'; import { ethers } from 'ethers'; import { firstValueFrom } from 'rxjs'; + import { GetOperatorsPaginationOptions } from '../../common/types'; import { EnvironmentConfigService } from '../../common/config/env-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; @@ -27,7 +26,8 @@ import { MAX_LEADERS_COUNT, MIN_STAKED_AMOUNT, REPUTATION_PLACEHOLDER, -} from '../../common/constants/operator'; + type ChainId, +} from '../../common/constants'; import * as httpUtils from '../../common/utils/http'; import { OperatorsOrderBy } from '../../common/enums/operator'; import { ReputationLevel } from '../../common/enums/reputation'; diff --git a/packages/apps/dashboard/server/src/modules/details/details.spec.ts b/packages/apps/dashboard/server/src/modules/details/details.spec.ts index 0b0dc899d3..6cbc1dae10 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.spec.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.spec.ts @@ -1,5 +1,4 @@ import { - ChainId, IOperator, KVStoreUtils, OperatorUtils, @@ -13,6 +12,7 @@ import { EnvironmentConfigService } from '../../common/config/env-config.service import { NetworkConfigService } from '../../common/config/network-config.service'; import { OperatorsOrderBy } from '../../common/enums/operator'; import { DetailsService } from './details.service'; +import { DevelopmentChainId } from '../../common/constants'; jest.mock('@human-protocol/sdk', () => ({ ...jest.requireActual('@human-protocol/sdk'), @@ -54,7 +54,7 @@ describe('DetailsService', () => { useValue: { getAvailableNetworks: jest .fn() - .mockResolvedValue([ChainId.MAINNET]), + .mockResolvedValue([DevelopmentChainId.SEPOLIA]), }, }, { @@ -82,7 +82,7 @@ describe('DetailsService', () => { .spyOn(httpService as any, 'get') .mockReturnValue(of({ data: mockReputations })); - const result = await service.getOperators(ChainId.ALL); + const result = await service.getOperators(DevelopmentChainId.POLYGON_AMOY); expect(result).toEqual([ expect.objectContaining({ @@ -101,7 +101,7 @@ describe('DetailsService', () => { .mockResolvedValue(mockOperators as IOperator[]); jest.spyOn(httpService as any, 'get').mockReturnValue(of({ data: [] })); - const result = await service.getOperators(ChainId.ALL); + const result = await service.getOperators(DevelopmentChainId.BSC_TESTNET); expect(result).toEqual([ expect.objectContaining({ @@ -135,7 +135,7 @@ describe('DetailsService', () => { .spyOn(httpService as any, 'get') .mockReturnValue(of({ data: mockReputations })); - const result = await service.getOperators(ChainId.POLYGON_AMOY, { + const result = await service.getOperators(DevelopmentChainId.POLYGON_AMOY, { orderBy: OperatorsOrderBy.REPUTATION, orderDirection: OrderDirection.DESC, first: 5, @@ -162,7 +162,7 @@ describe('DetailsService', () => { .spyOn(httpService, 'get') .mockReturnValue(throwError(() => new Error('API error'))); - const result = await service.getOperators(ChainId.ALL); + const result = await service.getOperators(DevelopmentChainId.BSC_TESTNET); expect(result).toEqual([ expect.objectContaining({ @@ -183,7 +183,10 @@ describe('DetailsService', () => { .spyOn(KVStoreUtils, 'getKVStoreData') .mockResolvedValue(mockKVStoreData); - const result = await service.getKVStoreData(ChainId.MAINNET, '0x123'); + const result = await service.getKVStoreData( + DevelopmentChainId.SEPOLIA, + '0x123', + ); expect(result).toEqual([ expect.objectContaining({ key: 'key1', value: 'value1' }), diff --git a/packages/apps/dashboard/server/src/modules/details/dto/common.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/common.dto.ts new file mode 100644 index 0000000000..2abbbc0869 --- /dev/null +++ b/packages/apps/dashboard/server/src/modules/details/dto/common.dto.ts @@ -0,0 +1,9 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsChainId } from '../../../common/validators'; +import { type ChainId, ChainIds } from '../../../common/constants'; + +export class ChainIdQueryDto { + @ApiProperty({ enum: ChainIds }) + @IsChainId() + public chainId: ChainId; +} diff --git a/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts index 6f6fdf8f0e..c6fc316f3b 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/details-pagination.dto.ts @@ -1,6 +1,6 @@ -import { ChainId, OrderDirection } from '@human-protocol/sdk'; +import { OrderDirection } from '@human-protocol/sdk'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { Transform, Type } from 'class-transformer'; +import { Type } from 'class-transformer'; import { IsEnum, IsIn, @@ -13,14 +13,9 @@ import { import { OperatorsOrderBy } from '../../../common/enums/operator'; import { IsRoleValid } from './validation/role-validation'; +import { ChainIdQueryDto } from './common.dto'; -export class OperatorsPaginationDto { - @ApiProperty({ enum: ChainId }) - @IsEnum(ChainId) - @IsIn(Object.values(ChainId).filter((id) => id !== ChainId.ALL)) - @Transform(({ value }) => parseInt(value)) - public chainId: ChainId; - +export class OperatorsPaginationDto extends ChainIdQueryDto { @ApiPropertyOptional({ enum: OperatorsOrderBy, default: OperatorsOrderBy.STAKED_AMOUNT, @@ -51,13 +46,7 @@ export class OperatorsPaginationDto { public first?: number = 10; } -export class DetailsTransactionsPaginationDto { - @ApiProperty({ enum: ChainId }) - @IsEnum(ChainId) - @IsIn(Object.values(ChainId)) - @Transform(({ value }) => parseInt(value)) - public chainId: ChainId; - +export class DetailsTransactionsPaginationDto extends ChainIdQueryDto { @ApiPropertyOptional({ minimum: 0, default: 10, @@ -81,13 +70,7 @@ export class DetailsTransactionsPaginationDto { public skip?: number = 0; } -export class DetailsEscrowsPaginationDto { - @ApiProperty({ enum: ChainId }) - @IsEnum(ChainId) - @IsIn(Object.values(ChainId)) - @Transform(({ value }) => parseInt(value)) - public chainId: ChainId; - +export class DetailsEscrowsPaginationDto extends ChainIdQueryDto { @ApiProperty() @IsString() @IsRoleValid() diff --git a/packages/apps/dashboard/server/src/modules/details/dto/details-response.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/details-response.dto.ts index 38d37873af..0e9346ae61 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/details-response.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/details-response.dto.ts @@ -1,11 +1,11 @@ import { IsArray, IsOptional } from 'class-validator'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { ChainId } from '@human-protocol/sdk'; import { EscrowDto, EscrowPaginationDto } from './escrow.dto'; import { TransactionPaginationDto } from './transaction.dto'; import { OperatorDto } from './operator.dto'; import { WalletDto } from './wallet.dto'; +import { ChainId, ProductionChainId } from '../../../common/constants'; export class DetailsResponseDto { @ApiProperty() @@ -28,7 +28,7 @@ export class DetailsPaginationResponseDto { @ApiProperty({ example: '0xb794f5ea0ba39494ce839613fffba74279579268' }) public address: string; - @ApiProperty({ example: ChainId.POLYGON_AMOY }) + @ApiProperty({ example: ProductionChainId.POLYGON_MAINNET }) public chainId: ChainId; @ApiProperty({ example: 10 }) diff --git a/packages/apps/dashboard/server/src/modules/details/dto/escrow.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/escrow.dto.ts index 69e8e7bc00..c2c5f5a5e1 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/escrow.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/escrow.dto.ts @@ -1,11 +1,10 @@ import { Expose } from 'class-transformer'; -import { IsEnum, IsNumber, IsString, IsUrl } from 'class-validator'; +import { IsNumber, IsString, IsUrl } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { ChainId } from '@human-protocol/sdk'; +import { ChainId, ProductionChainId } from '../../../common/constants'; export class EscrowDto { - @ApiProperty({ example: ChainId.POLYGON_AMOY }) - @IsEnum(ChainId) + @ApiProperty({ example: ProductionChainId.POLYGON_MAINNET }) @Expose() public chainId: ChainId; @@ -86,8 +85,7 @@ export class EscrowDto { } export class EscrowPaginationDto { - @ApiProperty({ example: ChainId.POLYGON_AMOY }) - @IsEnum(ChainId) + @ApiProperty({ example: ProductionChainId.POLYGON_MAINNET }) @Expose() public chainId: ChainId; diff --git a/packages/apps/dashboard/server/src/modules/details/dto/operator.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/operator.dto.ts index d4bb4fd93a..abf0376cdb 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/operator.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/operator.dto.ts @@ -1,18 +1,17 @@ +import { Role } from '@human-protocol/sdk'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Expose, Transform } from 'class-transformer'; import { IsArray, - IsEnum, + IsNumber, + IsOptional, IsString, IsUrl, - IsOptional, - IsNumber, } from 'class-validator'; -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { ChainId, Role } from '@human-protocol/sdk'; +import { ChainId, ProductionChainId } from '../../../common/constants'; export class OperatorDto { - @ApiProperty({ example: ChainId.POLYGON_AMOY }) - @IsEnum(ChainId) + @ApiProperty({ example: ProductionChainId.POLYGON_MAINNET }) @Expose() public chainId: ChainId; diff --git a/packages/apps/dashboard/server/src/modules/details/dto/wallet.dto.ts b/packages/apps/dashboard/server/src/modules/details/dto/wallet.dto.ts index 51aff04d41..14311ea3c4 100644 --- a/packages/apps/dashboard/server/src/modules/details/dto/wallet.dto.ts +++ b/packages/apps/dashboard/server/src/modules/details/dto/wallet.dto.ts @@ -1,11 +1,10 @@ -import { ChainId } from '@human-protocol/sdk'; import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; -import { IsEnum, IsNumber, IsString } from 'class-validator'; +import { IsNumber, IsString } from 'class-validator'; +import { type ChainId, ProductionChainId } from '../../../common/constants'; export class WalletDto { - @ApiProperty({ example: ChainId.POLYGON_AMOY }) - @IsEnum(ChainId) + @ApiProperty({ example: ProductionChainId.POLYGON_MAINNET }) public chainId: ChainId; @ApiProperty({ example: '0xb794f5ea0ba39494ce839613fffba74279579268' }) diff --git a/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts b/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts index a5ad3a7c5b..3e6d9eacd0 100644 --- a/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts +++ b/packages/apps/dashboard/server/src/modules/networks/networks.controller.ts @@ -8,7 +8,7 @@ import { ValidationPipe, } from '@nestjs/common'; import { NetworksService } from './networks.service'; -import { ChainId } from '@human-protocol/sdk'; +import { ChainId } from '../../common/constants'; @ApiTags('Networks') @Controller('/networks') diff --git a/packages/apps/dashboard/server/src/modules/networks/network.service.spec.ts b/packages/apps/dashboard/server/src/modules/networks/networks.service.spec.ts similarity index 87% rename from packages/apps/dashboard/server/src/modules/networks/network.service.spec.ts rename to packages/apps/dashboard/server/src/modules/networks/networks.service.spec.ts index 166370dd98..b07df13a57 100644 --- a/packages/apps/dashboard/server/src/modules/networks/network.service.spec.ts +++ b/packages/apps/dashboard/server/src/modules/networks/networks.service.spec.ts @@ -1,5 +1,5 @@ import { createMock } from '@golevelup/ts-jest'; -import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; +import { NETWORKS, StatisticsClient } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { ConfigService } from '@nestjs/config'; @@ -7,6 +7,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { Cache } from 'cache-manager'; import { EnvironmentConfigService } from '../../common/config/env-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import { DevelopmentChainId } from '../../common/constants'; import { NetworksService } from './networks.service'; jest.mock('@human-protocol/sdk', () => ({ @@ -19,10 +20,9 @@ describe('NetworksService', () => { let cacheManager: Cache; beforeAll(async () => { - process.env.RPC_URL_POLYGON = 'https://testrpc.com'; - process.env.RPC_URL_BSC_MAINNET = 'https://testrpc.com'; - process.env.RPC_URL_ETHEREUM = 'https://testrpc.com'; - process.env.WEB3_ENV = 'mainnet'; + process.env.RPC_URL_SEPOLIA = 'https://testrpc.com'; + process.env.RPC_URL_POLYGON_AMOY = 'https://testrpc.com'; + process.env.RPC_URL_BSC_TESTNET = 'https://testrpc.com'; }); beforeEach(async () => { @@ -55,9 +55,9 @@ describe('NetworksService', () => { it('should regenerate network list when cache TTL expires', async () => { const mockNetworkList = [ - ChainId.MAINNET, - ChainId.POLYGON, - ChainId.BSC_MAINNET, + DevelopmentChainId.SEPOLIA, + DevelopmentChainId.POLYGON_AMOY, + DevelopmentChainId.BSC_TESTNET, ]; // Step 1: Initial request - populate cache @@ -100,7 +100,10 @@ describe('NetworksService', () => { }); it('should return cached networks if available', async () => { - const cachedNetworks = [ChainId.MAINNET, ChainId.POLYGON]; + const cachedNetworks = [ + DevelopmentChainId.SEPOLIA, + DevelopmentChainId.POLYGON_AMOY, + ]; jest.spyOn(cacheManager, 'get').mockResolvedValue(cachedNetworks); const result = await networksService.getOperatingNetworks(); @@ -125,7 +128,10 @@ describe('NetworksService', () => { const result = await networksService.getOperatingNetworks(); expect(result).toEqual( - expect.arrayContaining([ChainId.MAINNET, ChainId.POLYGON]), + expect.arrayContaining([ + DevelopmentChainId.SEPOLIA, + DevelopmentChainId.POLYGON_AMOY, + ]), ); expect(cacheManager.set).toHaveBeenCalledWith( @@ -154,8 +160,8 @@ describe('NetworksService', () => { it('should handle missing network configuration gracefully', async () => { jest.spyOn(cacheManager, 'get').mockResolvedValue(null); - const originalNetworkConfig = NETWORKS[ChainId.MAINNET]; - NETWORKS[ChainId.MAINNET] = undefined; + const originalNetworkConfig = NETWORKS[DevelopmentChainId.SEPOLIA]; + NETWORKS[DevelopmentChainId.SEPOLIA] = undefined; const mockStatisticsClient = { getHMTDailyData: jest @@ -172,10 +178,10 @@ describe('NetworksService', () => { const result = await networksService.getOperatingNetworks(); - expect(result).not.toContain(ChainId.MAINNET); + expect(result).not.toContain(DevelopmentChainId.SEPOLIA); expect(result).toEqual(expect.arrayContaining([])); - NETWORKS[ChainId.MAINNET] = originalNetworkConfig; + NETWORKS[DevelopmentChainId.SEPOLIA] = originalNetworkConfig; }); it('should handle errors in getHMTDailyData gracefully', async () => { diff --git a/packages/apps/dashboard/server/src/modules/networks/networks.service.ts b/packages/apps/dashboard/server/src/modules/networks/networks.service.ts index 822be223c0..d2f72d7bef 100644 --- a/packages/apps/dashboard/server/src/modules/networks/networks.service.ts +++ b/packages/apps/dashboard/server/src/modules/networks/networks.service.ts @@ -1,4 +1,4 @@ -import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; +import { NETWORKS, StatisticsClient } from '@human-protocol/sdk'; import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; import { Inject, Injectable } from '@nestjs/common'; @@ -9,6 +9,7 @@ import { } from '../../common/config/env-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { OPERATING_NETWORKS_CACHE_KEY } from '../../common/config/redis-config.service'; +import { ChainId } from '../../common/constants'; import logger from '../../logger'; @Injectable() diff --git a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts index 6b513c8047..c08b05d221 100644 --- a/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/kv-store/kv-store.gateway.ts @@ -1,4 +1,9 @@ -import { ChainId, KVStoreKeys, KVStoreUtils } from '@human-protocol/sdk'; +import { + ChainId, + InvalidKeyError, + KVStoreKeys, + KVStoreUtils, +} from '@human-protocol/sdk'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { HttpException, Inject, Injectable } from '@nestjs/common'; import { Cache } from 'cache-manager'; @@ -30,24 +35,26 @@ export class KvStoreGateway { const chainId: ChainId = Number(network?.chainId); oracleUrl = await KVStoreUtils.get(chainId, address, KVStoreKeys.url); - } catch (e) { - if (e.toString().includes('Error: Invalid address')) { + } catch (error) { + if (error instanceof InvalidKeyError) { + oracleUrl = ''; + } else if (error.toString().includes('Error: Invalid address')) { throw new HttpException( `Unable to retrieve URL from address: ${address}`, 400, ); } else { throw new Error( - `Error, while fetching exchange oracle URL from kv-store: ${e}`, + `Error, while fetching exchange oracle URL from kv-store`, + { + cause: error, + }, ); } } if (!oracleUrl || oracleUrl === '') { - throw new HttpException( - `Unable to retrieve URL from address: ${address}`, - 400, - ); + throw new HttpException('Oracle does not have URL set in KV store', 422); } oracleUrl = oracleUrl.replace(/\/$/, ''); diff --git a/packages/apps/job-launcher/server/src/common/guards/jwt.auth.ts b/packages/apps/job-launcher/server/src/common/guards/jwt.auth.ts index e60297c4fa..ee9bdf97f7 100644 --- a/packages/apps/job-launcher/server/src/common/guards/jwt.auth.ts +++ b/packages/apps/job-launcher/server/src/common/guards/jwt.auth.ts @@ -6,11 +6,14 @@ import { } from '@nestjs/common'; import { ModuleRef, Reflector } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; +import logger from '../../logger'; import { AuthError, ForbiddenError } from '../errors'; import { ApiKeyGuard } from './apikey.auth'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt-http') implements CanActivate { + private readonly logger = logger.child({ context: JwtAuthGuard.name }); + constructor( private readonly reflector: Reflector, private readonly moduleRef: ModuleRef, @@ -29,7 +32,9 @@ export class JwtAuthGuard extends AuthGuard('jwt-http') implements CanActivate { try { return apiKeyGuard.canActivate(context); } catch (apiKeyError) { - console.error('API key auth failed:', apiKeyError); + this.logger.error('API key auth failed', { + error: apiKeyError, + }); } } diff --git a/packages/apps/job-launcher/server/src/logger/__mocks__/index.ts b/packages/apps/job-launcher/server/src/logger/__mocks__/index.ts new file mode 100644 index 0000000000..bc3cb79069 --- /dev/null +++ b/packages/apps/job-launcher/server/src/logger/__mocks__/index.ts @@ -0,0 +1,11 @@ +import type { Logger } from '@human-protocol/logger'; + +const logger: Logger = { + child: () => logger, + info: jest.fn(), + debug: jest.fn(), + error: jest.fn(), + warn: jest.fn(), +}; + +export default logger; diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts index b84aedfc8a..b7f7706a97 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.spec.ts @@ -1,4 +1,5 @@ jest.mock('@human-protocol/sdk'); +jest.mock('../../logger'); import { faker } from '@faker-js/faker'; import { createMock } from '@golevelup/ts-jest'; @@ -42,6 +43,7 @@ import { } from '../../common/enums/job'; import { WebhookStatus } from '../../common/enums/webhook'; import { ConflictError } from '../../common/errors'; +import logger from '../../logger'; import { ContentModerationRequestRepository } from '../content-moderation/content-moderation-request.repository'; import { GCVContentModerationService } from '../content-moderation/gcv-content-moderation.service'; import { JobEntity } from '../job/job.entity'; @@ -953,18 +955,19 @@ describe('CronJobService', () => { }); it('should handle errors and log them', async () => { - const loggerErrorSpy = jest.spyOn((service as any).logger, 'error'); + const syntheticError = new Error('Test error'); jest .spyOn(EscrowUtils, 'getStatusEvents') - .mockRejectedValue(new Error('Test error')); + .mockRejectedValue(syntheticError); await service.syncJobStatuses(); - expect(loggerErrorSpy).toHaveBeenCalledWith( + expect(logger.error).toHaveBeenCalledWith( 'Error in syncJobStatuses cron job', - expect.any(Error), + { + error: syntheticError, + }, ); - loggerErrorSpy.mockRestore(); }); it('should complete the cron job entity to unlock', async () => { diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts index 37022526eb..12f245123b 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts @@ -468,12 +468,15 @@ export class CronJobService { await this.cronJobRepository.save(cronJob); } } catch (error) { - this.logger.error('Error in syncJobStatuses cron job', error); + this.logger.error('Error in syncJobStatuses cron job', { + error, + }); } this.logger.debug('Update jobs STOP'); await this.completeCronJob(cronJob); } + private async createCancellationWebhooks( jobEntity: JobEntity, oracleType: OracleType, diff --git a/packages/apps/job-launcher/server/src/modules/web3/web3.controller.ts b/packages/apps/job-launcher/server/src/modules/web3/web3.controller.ts index 9873601138..1c16344714 100644 --- a/packages/apps/job-launcher/server/src/modules/web3/web3.controller.ts +++ b/packages/apps/job-launcher/server/src/modules/web3/web3.controller.ts @@ -8,6 +8,7 @@ import { AvailableOraclesDto, GetAvailableOraclesDto, GetReputationOraclesDto, + validChainIds, } from './web3.dto'; @ApiTags('Web3') @@ -29,9 +30,7 @@ export class Web3Controller { type: 'array', items: { type: 'number', - enum: Object.values(ChainId).filter( - (value) => typeof value === 'number' && value > 0, - ) as number[], + enum: validChainIds, }, }, }) diff --git a/packages/apps/job-launcher/server/src/modules/web3/web3.dto.ts b/packages/apps/job-launcher/server/src/modules/web3/web3.dto.ts index ea3b2dc6ce..56a0131a65 100644 --- a/packages/apps/job-launcher/server/src/modules/web3/web3.dto.ts +++ b/packages/apps/job-launcher/server/src/modules/web3/web3.dto.ts @@ -1,6 +1,8 @@ import { ChainId, IOperator } from '@human-protocol/sdk'; +import { applyDecorators } from '@nestjs/common'; import { ApiProperty } from '@nestjs/swagger'; -import { IsString } from 'class-validator'; +import { Transform } from 'class-transformer'; +import { IsIn, IsString } from 'class-validator'; export class OracleDataDto implements Partial { address: string; @@ -9,6 +11,17 @@ export class OracleDataDto implements Partial { jobTypes?: string[] | null; } +export const validChainIds = Object.values(ChainId).filter( + (value) => typeof value === 'number' && value > 0, +) as number[]; + +function IsValidChainId() { + return applyDecorators( + IsIn(validChainIds), + Transform(({ value }) => Number(value)), + ); +} + export class AvailableOraclesDto { @ApiProperty({ description: 'List of addresses of exchange oracles', @@ -22,8 +35,8 @@ export class AvailableOraclesDto { } export class GetAvailableOraclesDto { - @ApiProperty({ name: 'chain_id' }) - @IsString() + @ApiProperty({ name: 'chain_id', enum: validChainIds }) + @IsValidChainId() chainId: ChainId; @ApiProperty({ name: 'job_type' }) @@ -36,8 +49,8 @@ export class GetAvailableOraclesDto { } export class GetReputationOraclesDto { - @ApiProperty({ name: 'chain_id' }) - @IsString() + @ApiProperty({ name: 'chain_id', enum: validChainIds }) + @IsValidChainId() chainId: ChainId; @ApiProperty({ name: 'job_type' }) diff --git a/packages/apps/reputation-oracle/server/src/common/validators/index.ts b/packages/apps/reputation-oracle/server/src/common/validators/index.ts index e71aa847a1..a01d8fb1f1 100644 --- a/packages/apps/reputation-oracle/server/src/common/validators/index.ts +++ b/packages/apps/reputation-oracle/server/src/common/validators/index.ts @@ -23,17 +23,21 @@ export function IsLowercasedEmail() { ); } +function unknownToLowerCase(v: unknown): string { + return `${v}`.toLowerCase(); +} + export function IsLowercasedEnum( entity: object, validationOptions?: ValidationOptions, ) { return applyDecorators( IsEnum(entity, validationOptions), - Transform(({ value }) => { - if (validationOptions?.each) { - return value.map((v: string) => v.toLowerCase()); + Transform(({ value }: { value: unknown[] | unknown }) => { + if (validationOptions?.each && Array.isArray(value)) { + return value.map(unknownToLowerCase); } - return value.toLowerCase(); + return unknownToLowerCase(value); }), ); } From 0f32fc00990ed3786fa6e6c87a5e478afd49a8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Fri, 19 Dec 2025 10:21:47 +0100 Subject: [PATCH 12/21] [SDK][Typescript] Change contract visibility in EscrowClient and KVStoreClient (#3724) --- .changeset/eleven-clubs-itch.md | 5 +++++ packages/sdk/typescript/human-protocol-sdk/src/escrow.ts | 2 +- packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/eleven-clubs-itch.md diff --git a/.changeset/eleven-clubs-itch.md b/.changeset/eleven-clubs-itch.md new file mode 100644 index 0000000000..1a6378d01e --- /dev/null +++ b/.changeset/eleven-clubs-itch.md @@ -0,0 +1,5 @@ +--- +"@human-protocol/sdk": patch +--- + +Change contract visibility from private to public in EscrowClient and KVStoreClient diff --git a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts index 6ade2c66e6..cbbf522dde 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts @@ -146,7 +146,7 @@ import { * ``` */ export class EscrowClient extends BaseEthersClient { - private escrowFactoryContract: EscrowFactory; + public escrowFactoryContract: EscrowFactory; /** * **EscrowClient constructor** diff --git a/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts b/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts index 518217ee01..c30ca0f9d4 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts @@ -96,7 +96,7 @@ import { IKVStore, SubgraphOptions } from './interfaces'; */ export class KVStoreClient extends BaseEthersClient { - private contract: KVStore; + public contract: KVStore; /** * **KVStoreClient constructor** From 2460c292d2a03178fff571270ab19d14d3129ff5 Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Mon, 5 Jan 2026 12:39:46 +0300 Subject: [PATCH 13/21] [Logger] fix: peer deps versions range (#3732) --- .changeset/swift-impalas-scream.md | 5 +++++ packages/libs/logger/package.json | 2 +- yarn.lock | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/swift-impalas-scream.md diff --git a/.changeset/swift-impalas-scream.md b/.changeset/swift-impalas-scream.md new file mode 100644 index 0000000000..bfb14f5fbb --- /dev/null +++ b/.changeset/swift-impalas-scream.md @@ -0,0 +1,5 @@ +--- +"@human-protocol/logger": patch +--- + +Fixed nest/common peer dep version range diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json index f7d38d690f..1313a673a2 100644 --- a/packages/libs/logger/package.json +++ b/packages/libs/logger/package.json @@ -34,7 +34,7 @@ "typescript-eslint": "^8.35.1" }, "peerDependencies": { - "@nestjs/common": "^10.2.7" + "@nestjs/common": ">=10.0.0 <12.0.0" }, "engines": { "node": ">=22" diff --git a/yarn.lock b/yarn.lock index 09d8305a27..3dbb7dc88a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4946,7 +4946,7 @@ __metadata: typescript: "npm:^5.8.3" typescript-eslint: "npm:^8.35.1" peerDependencies: - "@nestjs/common": ^10.2.7 + "@nestjs/common": ">=10.0.0 <12.0.0" languageName: unknown linkType: soft From 6a01975ed76bb063c46e4c8205162c2d7d66cbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Mon, 5 Jan 2026 13:50:34 +0100 Subject: [PATCH 14/21] Integrate staking amount requirement (#3632) Co-authored-by: KirillKirill Co-authored-by: Dmitry Nechay --- packages/apps/human-app/frontend/.env.example | 1 + .../assets/icons-dark-mode/content-copy.svg | 3 + .../assets/icons-dark-mode/delete-icon.svg | 3 + .../src/assets/icons-dark-mode/edit-icon.svg | 3 + .../src/assets/icons/content-copy.svg | 3 + .../frontend/src/assets/icons/delete-icon.svg | 3 + .../frontend/src/assets/icons/edit-icon.svg | 3 + packages/apps/human-app/frontend/src/main.tsx | 44 +-- .../src/modules/auth/context/auth-context.tsx | 1 + .../worker/hooks/use-exchange-api-keys.ts | 58 ++++ .../worker/hooks/use-idv-notification.tsx | 18 -- .../src/modules/worker/hooks/use-staking.ts | 11 + .../should-navigate-to-registration.ts | 6 +- .../hooks/use-available-jobs-filter-modal.tsx | 6 +- .../src/modules/worker/jobs/jobs.page.tsx | 16 +- .../hooks/use-my-jobs-filter-modal.tsx | 6 +- .../profile/components/add-api-key-modal.tsx | 252 ++++++++++++++++ .../profile/components/api-key-data.tsx | 101 +++++++ .../profile/components/custom-text-field.tsx | 42 +++ .../components/delete-api-key-modal.tsx | 118 ++++++++ .../profile/components/edit-api-key-modal.tsx | 280 ++++++++++++++++++ .../identity-verification-control.tsx | 2 +- .../worker/profile/components/index.ts | 9 +- .../profile/components/modal-states.tsx | 55 ++++ .../profile/components/profile-actions.tsx | 17 -- .../profile/components/profile-data.tsx | 23 +- .../profile/components/staking-info.tsx | 185 ++++++++++++ .../components/wallet-connect-done.tsx | 102 +++++-- .../profile/hooks/use-api-key-modals.tsx | 52 ++++ .../worker/profile/hooks/use-start-idv.ts | 14 +- .../worker/profile/views/profile.page.tsx | 32 +- .../worker/providers/require-stake.tsx | 31 ++ .../services/exchangeApiKeys.service.ts | 46 +++ .../worker/services/staking.service.ts | 16 + .../drawer-menu-items-worker.tsx | 11 +- .../human-app/frontend/src/router/router.tsx | 37 ++- .../shared/components/data-entry/input.tsx | 6 +- .../src/shared/components/ui/icons.tsx | 21 ++ .../components/ui/modal/global-modal.tsx | 49 ++- .../components/ui/modal/modal-header.tsx | 42 --- .../src/shared/contexts/modal-context.tsx | 19 +- .../apps/human-app/frontend/src/shared/env.ts | 1 + .../frontend/src/shared/i18n/en.json | 44 ++- .../shared/providers/ui-config-provider.tsx | 44 +++ .../src/shared/services/ui-config.service.ts | 4 +- .../frontend/src/shared/styles/theme.ts | 7 + .../apps/human-app/frontend/vite.config.mjs | 5 + .../apps/human-app/server/src/app.module.ts | 8 + .../common/config/gateway-config.service.ts | 30 ++ .../server/src/common/enums/http-method.ts | 1 + .../enums/reputation-oracle-endpoints.ts | 6 + .../src/common/guards/strategy/jwt.http.ts | 2 + .../src/common/utils/jwt-token.model.ts | 2 + .../reputation-oracle.gateway.ts | 82 +++++ .../reputation-oracle.mapper.profile.ts | 13 + packages/apps/human-app/server/src/main.ts | 2 +- .../exchange-api-keys.controller.ts | 83 ++++++ .../exchange-api-keys.mapper.profile.ts | 20 ++ .../exchange-api-keys.module.ts | 13 + .../exchange-api-keys.service.ts | 28 ++ .../model/exchange-api-keys.model.ts | 44 +++ .../spec/exchange-api-keys.controller.spec.ts | 96 ++++++ .../spec/exchange-api-keys.fixtures.ts | 45 +++ .../spec/exchange-api-keys.service.mock.ts | 14 + .../spec/exchange-api-keys.service.spec.ts | 89 ++++++ .../job-assignment.controller.ts | 34 ++- .../spec/job-assignment.controller.spec.ts | 55 ++++ .../jobs-discovery.controller.ts | 12 + .../spec/jobs-discovery.controller.spec.ts | 19 +- .../modules/staking/model/staking.model.ts | 20 ++ .../staking/spec/staking.controller.spec.ts | 50 ++++ .../modules/staking/spec/staking.fixtures.ts | 11 + .../staking/spec/staking.service.mock.ts | 9 + .../staking/spec/staking.service.spec.ts | 55 ++++ .../src/modules/staking/staking.controller.ts | 25 ++ .../src/modules/staking/staking.module.ts | 12 + .../src/modules/staking/staking.service.ts | 19 ++ .../ui-configuration.controller.spec.ts | 25 +- .../ui-configuration.controller.ts | 8 +- .../ui-configuration/ui-configuration.dto.ts | 11 + .../ui-configuration.module.ts | 2 + .../reputation-oracle/server/.env.example | 3 + .../server/src/app.module.ts | 4 + .../server/src/common/constants/index.ts | 17 ++ .../interceptors/transform.interceptor.ts | 4 + .../server/src/config/config.module.ts | 6 + .../src/config/encryption-config.service.ts | 14 + .../server/src/config/env-schema.ts | 17 ++ .../server/src/config/index.ts | 2 + .../src/config/staking-config.service.ts | 43 +++ .../server/src/database/database.module.ts | 2 + .../1761653939799-exchangeApiKeys.ts | 27 ++ .../server/src/modules/auth/auth.module.ts | 8 +- .../src/modules/auth/auth.service.spec.ts | 139 +++++++++ .../server/src/modules/auth/auth.service.ts | 45 +++ .../encryption/aes-encryption.service.spec.ts | 85 ++++++ .../encryption/aes-encryption.service.ts | 100 +++++++ .../modules/encryption/encryption.module.ts | 5 +- .../src/modules/encryption/fixtures/index.ts | 14 + .../exchange-api-key.entity.ts | 24 ++ .../exchange-api-keys.controller.ts | 136 +++++++++ .../exchange-api-keys.dto.ts | 48 +++ .../exchange-api-keys.error-filter.ts | 54 ++++ .../exchange-api-keys.errors.ts | 19 ++ .../exchange-api-keys.module.ts | 17 ++ .../exchange-api-keys.repository.ts | 30 ++ .../exchange-api-keys.service.spec.ts | 217 ++++++++++++++ .../exchange-api-keys.service.ts | 101 +++++++ .../exchange-api-keys/fixtures/index.ts | 25 ++ .../src/modules/exchange-api-keys/index.ts | 8 + .../server/src/modules/exchange/errors.ts | 15 + .../exchange/exchange-client.factory.ts | 31 ++ .../src/modules/exchange/exchange.module.ts | 9 + .../src/modules/exchange/fixtures/exchange.ts | 32 ++ .../src/modules/exchange/fixtures/index.ts | 1 + .../exchange/gate-exchange.client.spec.ts | 224 ++++++++++++++ .../modules/exchange/gate-exchange.client.ts | 148 +++++++++ .../server/src/modules/exchange/index.ts | 3 + .../exchange/mexc-exchange.client.spec.ts | 196 ++++++++++++ .../modules/exchange/mexc-exchange.client.ts | 101 +++++++ .../server/src/modules/exchange/types.ts | 16 + .../server/src/modules/exchange/utils.ts | 27 ++ .../server/src/modules/staking/index.ts | 3 + .../src/modules/staking/staking.controller.ts | 39 +++ .../server/src/modules/staking/staking.dto.ts | 23 ++ .../modules/staking/staking.error-filter.ts | 34 +++ .../src/modules/staking/staking.module.ts | 17 ++ .../modules/staking/staking.service.spec.ts | 212 +++++++++++++ .../src/modules/staking/staking.service.ts | 112 +++++++ .../server/src/modules/staking/types.ts | 11 + .../server/src/modules/web3/web3.service.ts | 4 + .../server/src/utils/stake.ts | 6 + 132 files changed, 5048 insertions(+), 227 deletions(-) create mode 100644 packages/apps/human-app/frontend/src/assets/icons-dark-mode/content-copy.svg create mode 100644 packages/apps/human-app/frontend/src/assets/icons-dark-mode/delete-icon.svg create mode 100644 packages/apps/human-app/frontend/src/assets/icons-dark-mode/edit-icon.svg create mode 100644 packages/apps/human-app/frontend/src/assets/icons/content-copy.svg create mode 100644 packages/apps/human-app/frontend/src/assets/icons/delete-icon.svg create mode 100644 packages/apps/human-app/frontend/src/assets/icons/edit-icon.svg create mode 100644 packages/apps/human-app/frontend/src/modules/worker/hooks/use-exchange-api-keys.ts delete mode 100644 packages/apps/human-app/frontend/src/modules/worker/hooks/use-idv-notification.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/hooks/use-staking.ts create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/add-api-key-modal.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/api-key-data.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/custom-text-field.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/delete-api-key-modal.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/edit-api-key-modal.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/modal-states.tsx delete mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-actions.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/components/staking-info.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-api-key-modals.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/providers/require-stake.tsx create mode 100644 packages/apps/human-app/frontend/src/modules/worker/services/exchangeApiKeys.service.ts create mode 100644 packages/apps/human-app/frontend/src/modules/worker/services/staking.service.ts delete mode 100644 packages/apps/human-app/frontend/src/shared/components/ui/modal/modal-header.tsx create mode 100644 packages/apps/human-app/frontend/src/shared/providers/ui-config-provider.tsx create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.mapper.profile.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/model/exchange-api-keys.model.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.controller.spec.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.fixtures.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.mock.ts create mode 100644 packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.spec.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/model/staking.model.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/spec/staking.controller.spec.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/spec/staking.fixtures.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/spec/staking.service.mock.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/spec/staking.service.spec.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/staking.controller.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/staking.module.ts create mode 100644 packages/apps/human-app/server/src/modules/staking/staking.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/config/encryption-config.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/config/staking-config.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/database/migrations/1761653939799-exchangeApiKeys.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/encryption/fixtures/index.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-key.entity.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.dto.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.error-filter.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.errors.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.repository.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/fixtures/index.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/index.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/errors.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/exchange-client.factory.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/exchange.module.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/exchange.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/index.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/index.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/types.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/exchange/utils.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/index.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/staking.controller.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/staking.dto.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/staking.error-filter.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/staking.module.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts create mode 100644 packages/apps/reputation-oracle/server/src/modules/staking/types.ts create mode 100644 packages/apps/reputation-oracle/server/src/utils/stake.ts diff --git a/packages/apps/human-app/frontend/.env.example b/packages/apps/human-app/frontend/.env.example index b0ea764d9e..8a13a7385e 100644 --- a/packages/apps/human-app/frontend/.env.example +++ b/packages/apps/human-app/frontend/.env.example @@ -25,6 +25,7 @@ VITE_H_CAPTCHA_ORACLE_TASK_TYPES=image_points,image_boxes # Other VITE_HUMAN_PROTOCOL_HELP_URL=https://docs.humanprotocol.org/ VITE_HUMAN_PROTOCOL_URL=https://humanprotocol.org/ +VITE_STAKING_DASHBOARD_URL=https://staking.humanprotocol.org/ VITE_HUMAN_SUPPORT_EMAIL=support@local.app VITE_NAVBAR__LINK__HOW_IT_WORK_URL=https://humanprotocol.org/ VITE_NAVBAR__LINK__PROTOCOL_URL=https://humanprotocol.org/ diff --git a/packages/apps/human-app/frontend/src/assets/icons-dark-mode/content-copy.svg b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/content-copy.svg new file mode 100644 index 0000000000..c4c4f89b16 --- /dev/null +++ b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/content-copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/apps/human-app/frontend/src/assets/icons-dark-mode/delete-icon.svg b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/delete-icon.svg new file mode 100644 index 0000000000..7be6824ded --- /dev/null +++ b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/delete-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/apps/human-app/frontend/src/assets/icons-dark-mode/edit-icon.svg b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/edit-icon.svg new file mode 100644 index 0000000000..37d6a7af11 --- /dev/null +++ b/packages/apps/human-app/frontend/src/assets/icons-dark-mode/edit-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/apps/human-app/frontend/src/assets/icons/content-copy.svg b/packages/apps/human-app/frontend/src/assets/icons/content-copy.svg new file mode 100644 index 0000000000..4423c76961 --- /dev/null +++ b/packages/apps/human-app/frontend/src/assets/icons/content-copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/apps/human-app/frontend/src/assets/icons/delete-icon.svg b/packages/apps/human-app/frontend/src/assets/icons/delete-icon.svg new file mode 100644 index 0000000000..77a98a0a93 --- /dev/null +++ b/packages/apps/human-app/frontend/src/assets/icons/delete-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/apps/human-app/frontend/src/assets/icons/edit-icon.svg b/packages/apps/human-app/frontend/src/assets/icons/edit-icon.svg new file mode 100644 index 0000000000..3bbfdd7749 --- /dev/null +++ b/packages/apps/human-app/frontend/src/assets/icons/edit-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/apps/human-app/frontend/src/main.tsx b/packages/apps/human-app/frontend/src/main.tsx index ccf792a2b6..bf9aaa190f 100644 --- a/packages/apps/human-app/frontend/src/main.tsx +++ b/packages/apps/human-app/frontend/src/main.tsx @@ -23,6 +23,7 @@ import { HomePageStateProvider } from '@/shared/contexts/homepage-state'; import { NotificationProvider } from '@/shared/providers/notifications-provider'; import { ModalProvider } from './shared/contexts/modal-context'; import { GlobalModal } from './shared/components/ui/modal/global-modal'; +import { UiConfigProvider } from './shared/providers/ui-config-provider'; const root = document.getElementById('root'); if (!root) throw Error('root element is undefined'); @@ -39,25 +40,30 @@ createRoot(root).render( - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/apps/human-app/frontend/src/modules/auth/context/auth-context.tsx b/packages/apps/human-app/frontend/src/modules/auth/context/auth-context.tsx index 2b2478b5f4..13b9001fed 100644 --- a/packages/apps/human-app/frontend/src/modules/auth/context/auth-context.tsx +++ b/packages/apps/human-app/frontend/src/modules/auth/context/auth-context.tsx @@ -11,6 +11,7 @@ const userDataSchema = z.object({ user_id: z.number(), reputation_network: z.string(), exp: z.number(), + is_stake_eligible: z.boolean(), }); export type UserData = z.infer; diff --git a/packages/apps/human-app/frontend/src/modules/worker/hooks/use-exchange-api-keys.ts b/packages/apps/human-app/frontend/src/modules/worker/hooks/use-exchange-api-keys.ts new file mode 100644 index 0000000000..c958791ca7 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/hooks/use-exchange-api-keys.ts @@ -0,0 +1,58 @@ +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { + deleteExchangeApiKeys, + enrollExchangeApiKeys, + getExchangeApiKeys, + getSupportedExchanges, +} from '../services/exchangeApiKeys.service'; + +function useGetSupportedExchanges() { + return useQuery({ + queryKey: ['supported-exchanges'], + queryFn: () => getSupportedExchanges(), + }); +} + +function useGetExchangeApiKeys() { + return useQuery({ + queryKey: ['exchange-api-keys'], + queryFn: () => getExchangeApiKeys(), + }); +} + +function useEnrollExchangeApiKeys() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationKey: ['enroll-exchange-api-keys'], + mutationFn: (data: { + exchange: string; + apiKey: string; + secretKey: string; + }) => enrollExchangeApiKeys(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['exchange-api-keys'] }); + queryClient.invalidateQueries({ queryKey: ['staking-summary'] }); + }, + }); +} + +function useDeleteExchangeApiKeys() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationKey: ['delete-exchange-api-keys'], + mutationFn: () => deleteExchangeApiKeys(), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['exchange-api-keys'] }); + queryClient.invalidateQueries({ queryKey: ['staking-summary'] }); + }, + }); +} + +export { + useGetSupportedExchanges, + useDeleteExchangeApiKeys, + useGetExchangeApiKeys, + useEnrollExchangeApiKeys, +}; diff --git a/packages/apps/human-app/frontend/src/modules/worker/hooks/use-idv-notification.tsx b/packages/apps/human-app/frontend/src/modules/worker/hooks/use-idv-notification.tsx deleted file mode 100644 index 7f6663e162..0000000000 --- a/packages/apps/human-app/frontend/src/modules/worker/hooks/use-idv-notification.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { - TopNotificationType, - useNotification, -} from '@/shared/hooks/use-notification'; -import { getErrorMessageForError } from '@/shared/errors'; -import type { ResponseError } from '@/shared/types/global.type'; - -export function useIdvErrorNotifications() { - const { showNotification } = useNotification(); - - return (error: ResponseError) => { - showNotification({ - type: TopNotificationType.WARNING, - message: getErrorMessageForError(error), - durationMs: 5000, - }); - }; -} diff --git a/packages/apps/human-app/frontend/src/modules/worker/hooks/use-staking.ts b/packages/apps/human-app/frontend/src/modules/worker/hooks/use-staking.ts new file mode 100644 index 0000000000..1556c072d6 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/hooks/use-staking.ts @@ -0,0 +1,11 @@ +import { useQuery } from '@tanstack/react-query'; +import { getStakingSummary } from '../services/staking.service'; + +function useGetStakingSummary() { + return useQuery({ + queryKey: ['staking-summary'], + queryFn: () => getStakingSummary(), + }); +} + +export { useGetStakingSummary }; diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts b/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts index 8bd98d3628..e92ec7dc33 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs-discovery/helpers/should-navigate-to-registration.ts @@ -8,7 +8,5 @@ export const shouldNavigateToRegistration = ( oracle: Oracle, registrationData?: RegistrationResult ): boolean => - Boolean( - oracle.registrationNeeded && - !registrationData?.oracle_addresses.includes(oracle.address) - ); + !!oracle.registrationNeeded && + !registrationData?.oracle_addresses.includes(oracle.address); diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-available-jobs-filter-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-available-jobs-filter-modal.tsx index f90e919961..6ce55c5c48 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-available-jobs-filter-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/available-jobs/hooks/use-available-jobs-filter-modal.tsx @@ -1,17 +1,17 @@ import { useModal } from '@/shared/contexts/modal-context'; -import { useGetUiConfig } from '@/shared/hooks'; +import { useUiConfig } from '@/shared/providers/ui-config-provider'; import { AvailableJobsFilterModal } from '../available-jobs-filter-modal'; export function useAvailableJobsFilterModal() { const { openModal, closeModal } = useModal(); - const { data: uiConfigData } = useGetUiConfig(); + const { uiConfig } = useUiConfig(); return { openModal: () => { openModal({ content: ( ), diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/jobs.page.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/jobs.page.tsx index 5e65b627ae..21364ccedf 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/jobs.page.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/jobs.page.tsx @@ -7,7 +7,7 @@ import { useIsMobile } from '@/shared/hooks/use-is-mobile'; import { useColorMode } from '@/shared/contexts/color-mode'; import { NoRecords } from '@/shared/components/ui/no-records'; import { PageCardLoader } from '@/shared/components/ui/page-card'; -import { useGetUiConfig } from '@/shared/hooks'; +import { useUiConfig } from '@/shared/providers/ui-config-provider'; import { useGetOracles } from '../hooks'; import { useGetOraclesNotifications } from '../hooks/use-get-oracles-notifications'; import { TabPanel } from './components'; @@ -30,19 +30,15 @@ export function JobsPage() { error, } = useGetOracles(); - const { - data: uiConfigData, - isPending: isPendingUiConfig, - isError: isErrorUiConfig, - } = useGetUiConfig(); + const { uiConfig, isUiConfigLoading, isUiConfigError } = useUiConfig(); const { address: oracle_address } = useParams<{ address: string }>(); const { t } = useTranslation(); const [activeTab, setActiveTab] = useState(0); const isMobile = useIsMobile(); - const isError = isErrorGetOracles || isErrorUiConfig; - const isPending = isPendingGetOracles || isPendingUiConfig; + const isError = isErrorGetOracles || isUiConfigError; + const isPending = isPendingGetOracles || isUiConfigLoading; const { onError } = useGetOraclesNotifications(); const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => { @@ -119,7 +115,7 @@ export function JobsPage() { ) : ( )} @@ -128,7 +124,7 @@ export function JobsPage() { ) : ( )} diff --git a/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/hooks/use-my-jobs-filter-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/hooks/use-my-jobs-filter-modal.tsx index 40a0c9c1be..a41ca0c491 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/hooks/use-my-jobs-filter-modal.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/jobs/my-jobs/hooks/use-my-jobs-filter-modal.tsx @@ -1,17 +1,17 @@ import { useModal } from '@/shared/contexts/modal-context'; -import { useGetUiConfig } from '@/shared/hooks'; import { MyJobsFilterModal } from '../components/mobile/my-jobs-filter-modal'; +import { useUiConfig } from '@/shared/providers/ui-config-provider'; export function useMyJobFilterModal() { const { openModal, closeModal } = useModal(); - const { data: uiConfigData } = useGetUiConfig(); + const { uiConfig } = useUiConfig(); return { openModal: () => { openModal({ content: ( ), diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/add-api-key-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/add-api-key-modal.tsx new file mode 100644 index 0000000000..f3b1ee6954 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/add-api-key-modal.tsx @@ -0,0 +1,252 @@ +import { zodResolver } from '@hookform/resolvers/zod'; +import { + Autocomplete, + Box, + FormControl, + FormHelperText, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { Controller, useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { z } from 'zod'; +import { Button } from '@/shared/components/ui/button'; +import { useIsMobile } from '@/shared/hooks'; +import { + useEnrollExchangeApiKeys, + useGetSupportedExchanges, +} from '../../hooks/use-exchange-api-keys'; +import { ModalError, ModalLoading, ModalSuccess } from './modal-states'; +import { useEffect } from 'react'; + +interface AddApiKeyModalProps { + onClose: () => void; + disableClose: (disable: boolean) => void; +} + +export function AddApiKeyModal({ onClose, disableClose }: AddApiKeyModalProps) { + const { t } = useTranslation(); + const { + mutate: enrollExchangeApiKey, + reset: resetMutation, + error, + isSuccess, + isPending, + isError, + isIdle, + } = useEnrollExchangeApiKeys(); + const isMobile = useIsMobile(); + const { data: supportedExchanges } = useGetSupportedExchanges(); + + useEffect(() => { + disableClose(isPending); + }, [isPending, disableClose]); + + const { + control, + handleSubmit, + formState: { errors }, + reset, + } = useForm({ + defaultValues: { + exchange: '', + apiKey: '', + secretKey: '', + }, + resolver: zodResolver( + z.object({ + exchange: z.string().min(1, t('validation.required')), + apiKey: z.string().trim().min(1, t('validation.required')), + secretKey: z.string().trim().min(1, t('validation.required')), + }) + ), + }); + + useEffect(() => { + return () => { + reset(); + resetMutation(); + }; + }, [reset, resetMutation]); + + const onSubmit = (data: { + exchange: string; + apiKey: string; + secretKey: string; + }) => { + enrollExchangeApiKey(data); + }; + + return ( +
+ + + {isMobile + ? t('worker.profile.apiKeyData.connectApiKey') + : t('worker.profile.apiKeyData.connectYourApiKey')} + + {isPending && } + {isIdle && ( + <> + + {t('worker.profile.apiKeyData.modalDescription')} + + + + ( + exchange.name) || + [] + } + getOptionLabel={(option) => { + const exchange = supportedExchanges?.find( + (exchange) => exchange.name === option + ); + return exchange?.display_name || option || ''; + }} + renderInput={(params) => ( + + )} + renderOption={(props, option) => { + const exchange = supportedExchanges?.find( + (exchange) => exchange.name === option + ); + return ( + + + {exchange?.display_name || exchange?.name} + + + ); + }} + {...field} + onChange={(_, value) => field.onChange(value)} + /> + )} + /> + {errors.exchange && ( + + {errors.exchange.message} + + )} + + + ( + + )} + /> + {errors.apiKey && ( + {errors.apiKey.message} + )} + + + + ( + + )} + /> + {errors.secretKey && ( + + {errors.secretKey.message} + + )} + + + )} + {isSuccess && ( + + + {t('worker.profile.apiKeyData.connectSuccess')} + + + )} + {isError && ( + + )} + {isIdle && ( + + )} + {(isPending || isSuccess) && ( + + )} + {isError && ( + + )} + + {t('worker.profile.apiKeyData.modalFooterAgreement')} + + +
+ ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/api-key-data.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/api-key-data.tsx new file mode 100644 index 0000000000..55cb3efb93 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/api-key-data.tsx @@ -0,0 +1,101 @@ +import { IconButton, Stack, Typography } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { Chip } from '@/shared/components/ui/chip'; +import { CustomTextField, CustomTextFieldDark } from './custom-text-field'; +import { useColorMode } from '@/shared/contexts/color-mode'; +import { DeleteIcon, EditIcon } from '@/shared/components/ui/icons'; +import { + useDeleteApiKeyModal, + useEditApiKeyModal, +} from '../hooks/use-api-key-modals'; +import { useGetExchangeApiKeys } from '../../hooks/use-exchange-api-keys'; + +export function ApiKeyData() { + const { isDarkMode } = useColorMode(); + const { t } = useTranslation(); + const { openModal: openEditApiKeyModal } = useEditApiKeyModal(); + const { openModal: openDeleteApiKeyModal } = useDeleteApiKeyModal(); + const { data: exchangeApiKeyData, isError: isExchangeApiKeyError } = + useGetExchangeApiKeys(); + + const textField = isDarkMode ? ( + + ) : ( + + ); + + return ( + + + + {t('worker.profile.apiKeyData.apiKey')} + + + + + {textField} + {exchangeApiKeyData?.exchange_name && ( + + + openEditApiKeyModal(exchangeApiKeyData.exchange_name) + } + > + + + + + + + )} + + + ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/custom-text-field.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/custom-text-field.tsx new file mode 100644 index 0000000000..de9183c226 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/custom-text-field.tsx @@ -0,0 +1,42 @@ +import { colorPalette } from '@/shared/styles/color-palette'; +import { + darkColorPalette, + onlyDarkModeColor, +} from '@/shared/styles/dark-color-palette'; +import { styled, TextField } from '@mui/material'; + +const CustomTextField = styled(TextField)(() => ({ + '& .Mui-disabled': { + height: '48px', + maxWidth: '376px', + color: colorPalette.text.disabledSecondary, + WebkitTextFillColor: `${colorPalette.text.disabledSecondary} !important`, + }, + '& .MuiOutlinedInput-root': { + '& fieldset': { + border: '1px dashed', + borderColor: `${colorPalette.text.primary} !important`, + color: colorPalette.text.disabledSecondary, + WebkitTextFillColor: colorPalette.text.disabledSecondary, + }, + }, +})); + +const CustomTextFieldDark = styled(TextField)(() => ({ + '& .Mui-disabled': { + height: '48px', + maxWidth: '376px', + color: darkColorPalette.text.disabledSecondary, + WebkitTextFillColor: `${darkColorPalette.text.disabledSecondary} !important`, + }, + '& .MuiOutlinedInput-root': { + '& fieldset': { + border: '1px dashed', + borderColor: `${onlyDarkModeColor.mainColorWithOpacity} !important`, + color: darkColorPalette.text.disabledSecondary, + WebkitTextFillColor: darkColorPalette.text.disabledSecondary, + }, + }, +})); + +export { CustomTextField, CustomTextFieldDark }; diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/delete-api-key-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/delete-api-key-modal.tsx new file mode 100644 index 0000000000..6a75d44423 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/delete-api-key-modal.tsx @@ -0,0 +1,118 @@ +import { Stack, Typography } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { Button } from '@/shared/components/ui/button'; +import { useIsMobile } from '@/shared/hooks'; +import { useDeleteExchangeApiKeys } from '../../hooks/use-exchange-api-keys'; +import { useEffect } from 'react'; +import { ModalError, ModalSuccess, ModalLoading } from './modal-states'; + +interface DeleteApiKeyModalProps { + onClose: () => void; + disableClose: (disable: boolean) => void; +} + +export function DeleteApiKeyModal({ + onClose, + disableClose, +}: DeleteApiKeyModalProps) { + const { t } = useTranslation(); + const { + mutate: deleteExchangeApiKey, + reset: resetMutation, + isSuccess, + isError, + isPending, + isIdle, + } = useDeleteExchangeApiKeys(); + const isMobile = useIsMobile(); + + const handleDeleteExchangeApiKey = () => { + deleteExchangeApiKey(); + }; + + useEffect(() => { + disableClose(isPending); + }, [isPending, disableClose]); + + useEffect(() => { + return () => { + resetMutation(); + }; + }, [resetMutation]); + + return ( + + + {t('worker.profile.apiKeyData.deleteApiKey')} + + {isPending && } + {isIdle && ( + <> + + {t('worker.profile.apiKeyData.deleteApiKeyConfirmation')} + + + {t('worker.profile.apiKeyData.deleteApiKeyDescription')} + + + )} + {isSuccess && ( + + + {t('worker.profile.apiKeyData.deleteKeySuccess')} + + + )} + {isError && ( + + )} + {isIdle && ( + + + + + )} + {(isPending || isSuccess) && ( + + )} + {isError && ( + + )} + + ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/edit-api-key-modal.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/edit-api-key-modal.tsx new file mode 100644 index 0000000000..9141eb9b02 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/edit-api-key-modal.tsx @@ -0,0 +1,280 @@ +import { zodResolver } from '@hookform/resolvers/zod'; +import { + Autocomplete, + Box, + FormControl, + FormHelperText, + Stack, + TextField, + Typography, +} from '@mui/material'; +import { Controller, useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { z } from 'zod'; +import { Button } from '@/shared/components/ui/button'; +import { useIsMobile } from '@/shared/hooks'; +import { useEffect } from 'react'; +import { + useEnrollExchangeApiKeys, + useGetSupportedExchanges, +} from '../../hooks/use-exchange-api-keys'; +import { ModalError, ModalLoading, ModalSuccess } from './modal-states'; + +interface EditApiKeyModalProps { + exchangeName: string; + onClose: () => void; + disableClose: (disable: boolean) => void; +} + +export function EditApiKeyModal({ + onClose, + exchangeName, + disableClose, +}: EditApiKeyModalProps) { + const { t } = useTranslation(); + const isMobile = useIsMobile(); + const { + mutate: postExchangeApiKey, + reset: resetMutation, + error, + isSuccess, + isError, + isPending, + isIdle, + } = useEnrollExchangeApiKeys(); + const { data: supportedExchanges } = useGetSupportedExchanges(); + + const { + control, + handleSubmit, + formState: { errors }, + reset, + } = useForm({ + defaultValues: { + exchange: '', + apiKey: '', + secretKey: '', + }, + resolver: zodResolver( + z.object({ + exchange: z.string().min(1, t('validation.required')), + apiKey: z.string().trim().min(1, t('validation.required')), + secretKey: z.string().trim().min(1, t('validation.required')), + }) + ), + }); + + useEffect(() => { + if (exchangeName && supportedExchanges) { + reset({ + exchange: exchangeName, + apiKey: '', + secretKey: '', + }); + } + }, [exchangeName, reset, supportedExchanges]); + + useEffect(() => { + disableClose(isPending); + }, [isPending, disableClose]); + + useEffect(() => { + return () => { + reset(); + resetMutation(); + }; + }, [reset, resetMutation]); + + const onSubmit = (data: { + exchange: string; + apiKey: string; + secretKey: string; + }) => { + postExchangeApiKey(data); + }; + + return ( +
+ + + {t('worker.profile.apiKeyData.editApiKey')} + + {isPending && } + {isIdle && ( + <> + + {t('worker.profile.apiKeyData.modalDescription')} + + + + ( + exchange.name) || + [] + } + getOptionLabel={(option) => { + const exchange = supportedExchanges?.find( + (exchange) => exchange.name === option + ); + return exchange?.display_name || option || ''; + }} + renderInput={(params) => ( + + )} + renderOption={(props, option) => { + const exchange = supportedExchanges?.find( + (exchange) => exchange.name === option + ); + return ( + + + {exchange?.display_name || exchange?.name} + + + ); + }} + {...field} + onChange={(_, value) => field.onChange(value)} + /> + )} + /> + {errors.exchange && ( + + {errors.exchange.message} + + )} + + + ( + + )} + /> + {errors.apiKey && ( + {errors.apiKey.message} + )} + + + + ( + + )} + /> + {errors.secretKey && ( + + {errors.secretKey.message} + + )} + + + )} + {isSuccess && ( + + + {t('worker.profile.apiKeyData.editSuccess')} + + + )} + {isError && ( + + )} + {isIdle && ( + + + + + )} + {(isPending || isSuccess) && ( + + )} + {isError && ( + + )} + +
+ ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/identity-verification-control.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/identity-verification-control.tsx index b808043119..6acd2ab252 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/components/identity-verification-control.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/identity-verification-control.tsx @@ -29,7 +29,7 @@ export function IdentityVerificationControl() { return ( - {t('worker.profile.identityVerificationStatus')}:{' '} + {t('worker.profile.identityVerificationStatus')} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/index.ts b/packages/apps/human-app/frontend/src/modules/worker/profile/components/index.ts index 43ff1e202d..7df62f04b8 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/components/index.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/index.ts @@ -1,3 +1,10 @@ export * from './wallet-connect-done'; -export * from './profile-actions'; export * from './profile-data'; +export * from './identity-verification-control'; +export * from './wallet-connection-control'; +export * from './staking-info'; +export * from './api-key-data'; +export * from './custom-text-field'; +export * from './add-api-key-modal'; +export * from './edit-api-key-modal'; +export * from './delete-api-key-modal'; diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/modal-states.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/modal-states.tsx new file mode 100644 index 0000000000..5225e3bd2b --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/modal-states.tsx @@ -0,0 +1,55 @@ +import CheckIcon from '@mui/icons-material/CheckCircle'; +import { Loader } from '@/shared/components/ui/loader'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import CloseIcon from '@mui/icons-material/Cancel'; + +export function ModalLoading() { + return ( + + + + ); +} + +export function ModalSuccess({ children }: { children: React.ReactNode }) { + return ( + <> + + + + {children} + + ); +} + +export function ModalError({ message }: { message: string }) { + return ( + <> + + + + + {message} + + + ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-actions.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-actions.tsx deleted file mode 100644 index 56551421f6..0000000000 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-actions.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import Grid from '@mui/material/Grid'; -import { IdentityVerificationControl } from './identity-verification-control'; -import { WalletConnectionControl } from './wallet-connection-control'; - -export function ProfileActions() { - return ( - - - - - - - - - - ); -} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-data.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-data.tsx index b3222fe956..42278a97c8 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-data.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/profile-data.tsx @@ -1,5 +1,4 @@ -import Grid from '@mui/material/Grid'; -import Typography from '@mui/material/Typography'; +import { Stack, Typography } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import { useAuthenticatedUser } from '@/modules/auth/hooks/use-authenticated-user'; @@ -13,8 +12,8 @@ export function ProfileData() { const { user } = useAuthenticatedUser(); const { t } = useTranslation(); return ( - - + + {t('worker.profile.email')} {user.email} - - + + + + {t('worker.profile.password')} + - - + + ); } diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/staking-info.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/staking-info.tsx new file mode 100644 index 0000000000..7c24f973db --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/staking-info.tsx @@ -0,0 +1,185 @@ +import { Button, IconButton, Skeleton, Stack, Typography } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { Chip } from '@/shared/components/ui/chip'; +import { env } from '@/shared/env'; +import { useAddApiKeyModal } from '../hooks/use-api-key-modals'; +import { ApiKeyData } from './'; +import { useGetStakingSummary } from '../../hooks/use-staking'; +import { RefreshIcon } from '@/shared/components/ui/icons'; +import { useGetExchangeApiKeys } from '../../hooks/use-exchange-api-keys'; +import { useAuthenticatedUser } from '@/modules/auth/hooks/use-authenticated-user'; +import { useEffect, useRef, useState } from 'react'; +import { useAccessTokenRefresh } from '@/api/hooks/use-access-token-refresh'; +import { colorPalette } from '@/shared/styles/color-palette'; +import { useGetUiConfig } from '@/shared/hooks/use-get-ui-config'; + +export function StakingInfo() { + const [isPromptExpanded, setIsPromptExpanded] = useState(false); + const tokenRefreshLock = useRef(false); + + const { user, updateUserData } = useAuthenticatedUser(); + const { refreshAccessTokenAsync } = useAccessTokenRefresh(); + const { t } = useTranslation(); + + const { openModal: openAddApiKeyModal } = useAddApiKeyModal(); + const { data: exchangeApiKeyData, isLoading: isExchangeApiKeyLoading } = + useGetExchangeApiKeys(); + const { + data: stakingSummary, + isLoading, + isError, + refetch, + isRefetching, + } = useGetStakingSummary(); + const { data: uiConfig, isLoading: isUiConfigLoading } = useGetUiConfig(); + + const isConnectButtonDisabled = + !!exchangeApiKeyData?.exchange_name || isExchangeApiKeyLoading; + + const stakedAmount = + Number(stakingSummary?.on_chain_stake || 0) + + Number(stakingSummary?.exchange_stake || 0); + + const isStakingError = + !!stakingSummary?.on_chain_error || + !!stakingSummary?.exchange_error || + isError; + + const isStaked = + isLoading || isStakingError || isUiConfigLoading + ? false + : stakedAmount >= Number(uiConfig?.minThreshold || '0'); + + useEffect(() => { + if (isRefetching || isLoading) return; + + if (isStaked !== user.is_stake_eligible) { + if (!tokenRefreshLock.current) { + tokenRefreshLock.current = true; + updateUserData({ is_stake_eligible: isStaked }); + void refreshAccessTokenAsync({ authType: 'web2' }); + } + } else { + tokenRefreshLock.current = false; + } + }, [ + isStaked, + user.is_stake_eligible, + refreshAccessTokenAsync, + isRefetching, + isLoading, + updateUserData, + ]); + + const handleRefreshStakingInfo = () => { + if (isRefetching || isLoading) return; + tokenRefreshLock.current = false; + refetch(); + }; + + return ( + + + + {t('worker.profile.stakingInfo.stakeHmt')} + + {isLoading || isRefetching ? ( + + ) : ( + + )} + + + {isPromptExpanded + ? t('worker.profile.stakingInfo.prompt', { + amount: uiConfig?.minThreshold, + }) + : t('worker.profile.stakingInfo.promptShort')}{' '} + + + + + {t('worker.profile.stakingInfo.stakedAmount')} + + svg > path': { + fill: + isRefetching || isLoading + ? colorPalette.button.disabled + : 'primary.main', + }, + }} + onClick={handleRefreshStakingInfo} + > + + + + {isLoading || isRefetching ? ( + + ) : ( + + {stakedAmount} HMT + + )} + + + + + + + ); +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/components/wallet-connect-done.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/components/wallet-connect-done.tsx index 263b262173..808b282eb1 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/components/wallet-connect-done.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/components/wallet-connect-done.tsx @@ -1,57 +1,97 @@ -import { Stack, TextField, Typography } from '@mui/material'; +import { IconButton, Stack, Tooltip, Typography } from '@mui/material'; import { t } from 'i18next'; -import styled from '@mui/material/styles/styled'; -import { colorPalette } from '@/shared/styles/color-palette'; import { useAuthenticatedUser } from '@/modules/auth/hooks/use-authenticated-user'; import { useColorMode } from '@/shared/contexts/color-mode'; -import { - darkColorPalette, - onlyDarkModeColor, -} from '@/shared/styles/dark-color-palette'; import { useWalletConnect } from '@/shared/contexts/wallet-connect'; import { Chip } from '@/shared/components/ui/chip'; - -const CustomTextField = styled(TextField)(() => ({ - '& .Mui-disabled': { - color: colorPalette.text.disabledSecondary, - WebkitTextFillColor: colorPalette.text.disabledSecondary, - }, -})); -const CustomTextFieldDark = styled(TextField)(() => ({ - '& .Mui-disabled': { - color: darkColorPalette.text.disabledSecondary, - WebkitTextFillColor: darkColorPalette.text.disabledSecondary, - }, - '& .MuiOutlinedInput-root': { - '& fieldset': { - borderColor: `${onlyDarkModeColor.mainColorWithOpacity} !important`, - }, - }, -})); +import { CopyIcon } from '@/shared/components/ui/icons'; +import { MouseEvent, useRef, useState } from 'react'; +import { shortenEscrowAddress } from '@/shared/helpers/evm'; +import { CustomTextField, CustomTextFieldDark } from './custom-text-field'; export function WalletConnectDone() { + const [isCopied, setIsCopied] = useState(false); + const timeoutRef = useRef(); const { isDarkMode } = useColorMode(); const { address } = useWalletConnect(); - const { user } = useAuthenticatedUser(); + const { + user: { wallet_address }, + } = useAuthenticatedUser(); + + if (!wallet_address) { + return null; + } + + const shortAddress = shortenEscrowAddress(wallet_address, 6, 6); + + const handleCopyClick = (e: MouseEvent) => { + if (isCopied) return; + + e.stopPropagation(); + navigator.clipboard.writeText(wallet_address); + setIsCopied(true); + + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + + timeoutRef.current = setTimeout(() => { + setIsCopied(false); + }, 1500); + }; const textFiled = isDarkMode ? ( - + + + + + + ), + }} + /> ) : ( - + + + + + + ), + }} + /> ); return ( - + - {t('worker.profile.wallet')}:{' '} + {t('worker.profile.wallet')} - {address && !user.wallet_address ? null : textFiled} + {address && !wallet_address ? null : textFiled} ); } diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-api-key-modals.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-api-key-modals.tsx new file mode 100644 index 0000000000..5d7db03586 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-api-key-modals.tsx @@ -0,0 +1,52 @@ +import { useModal } from '@/shared/contexts/modal-context'; +import { + AddApiKeyModal, + EditApiKeyModal, + DeleteApiKeyModal, +} from '../components'; + +export function useAddApiKeyModal() { + const { openModal, closeModal, setDisableClose } = useModal(); + + return { + openModal: () => + openModal({ + content: ( + + ), + }), + }; +} + +export function useEditApiKeyModal() { + const { openModal, closeModal, setDisableClose } = useModal(); + + return { + openModal: (exchangeName: string) => + openModal({ + content: ( + + ), + }), + }; +} + +export function useDeleteApiKeyModal() { + const { openModal, closeModal, setDisableClose } = useModal(); + + return { + openModal: () => + openModal({ + content: ( + + ), + }), + }; +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-start-idv.ts b/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-start-idv.ts index ef40c57822..ca9bc21805 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-start-idv.ts +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/hooks/use-start-idv.ts @@ -1,11 +1,13 @@ import { useEffect, useState, useCallback } from 'react'; -import { useIdvErrorNotifications } from '@/modules/worker/hooks/use-idv-notification'; import { ApiClientError } from '@/api'; import { useIdvStartMutation } from './use-start-idv-mutation'; +import { TopNotificationType, useNotification } from '@/shared/hooks'; +import { getErrorMessageForError } from '@/shared/errors'; export function useStartIdv() { const [isIdvAlreadyInProgress, setIsIdvAlreadyInProgress] = useState(false); - const onError = useIdvErrorNotifications(); + + const { showNotification } = useNotification(); const { data: idvStartData, isPending: idvStartIsPending, @@ -28,7 +30,11 @@ export function useStartIdv() { setIsIdvAlreadyInProgress(true); return; } - onError(idvStartMutationError); + showNotification({ + type: TopNotificationType.WARNING, + message: getErrorMessageForError(idvStartMutationError), + durationMs: 5000, + }); } if (idvStarted && idvStartData.url) { @@ -39,7 +45,7 @@ export function useStartIdv() { idvStartFailed, idvStarted, idvStartMutationError, - onError, + showNotification, ]); return { diff --git a/packages/apps/human-app/frontend/src/modules/worker/profile/views/profile.page.tsx b/packages/apps/human-app/frontend/src/modules/worker/profile/views/profile.page.tsx index 4f03b09c81..3fa42e64b9 100644 --- a/packages/apps/human-app/frontend/src/modules/worker/profile/views/profile.page.tsx +++ b/packages/apps/human-app/frontend/src/modules/worker/profile/views/profile.page.tsx @@ -1,4 +1,4 @@ -import { Grid, Paper } from '@mui/material'; +import { Paper, Stack } from '@mui/material'; import { useEffect } from 'react'; import { t } from 'i18next'; import { useIsMobile } from '@/shared/hooks/use-is-mobile'; @@ -8,7 +8,14 @@ import { TopNotificationType, useNotification, } from '@/shared/hooks/use-notification'; -import { ProfileData, ProfileActions } from '../components'; +import { + ProfileData, + IdentityVerificationControl, + WalletConnectionControl, + StakingInfo, +} from '../components'; +import { PageCardLoader } from '@/shared/components/ui/page-card/page-card-loader'; +import { useUiConfig } from '@/shared/providers/ui-config-provider'; export function WorkerProfilePage() { const { user } = useAuthenticatedUser(); @@ -16,6 +23,7 @@ export function WorkerProfilePage() { const { isConnected, initializing, web3ProviderMutation } = useWalletConnect(); const { showNotification } = useNotification(); + const { uiConfig, isUiConfigLoading } = useUiConfig(); useEffect(() => { if (initializing) return; @@ -42,6 +50,10 @@ export function WorkerProfilePage() { showNotification, ]); + if (isUiConfigLoading) { + return ; + } + return ( - + - - + + + {!!user.wallet_address && uiConfig?.stakingEligibilityEnabled && ( + + )} + ); } diff --git a/packages/apps/human-app/frontend/src/modules/worker/providers/require-stake.tsx b/packages/apps/human-app/frontend/src/modules/worker/providers/require-stake.tsx new file mode 100644 index 0000000000..c9e9843718 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/providers/require-stake.tsx @@ -0,0 +1,31 @@ +import { useAuthenticatedUser } from '@/modules/auth/hooks/use-authenticated-user'; +import { routerPaths } from '@/router/router-paths'; +import { protectedRoutes } from '@/router/routes'; +import { useUiConfig } from '@/shared/providers/ui-config-provider'; +import { Navigate, useLocation, matchPath } from 'react-router-dom'; + +const stakeProtectedPaths = protectedRoutes + .map((route) => route.routerProps.path) + .filter((path) => path !== routerPaths.worker.profile); + +export function RequireStake({ + children, +}: Readonly<{ children: JSX.Element }>) { + const { user } = useAuthenticatedUser(); + const location = useLocation(); + const { uiConfig } = useUiConfig(); + + const isStakeProtectedRoute = stakeProtectedPaths.some( + (path) => path && matchPath(path, location.pathname) + ); + + if ( + uiConfig?.stakingEligibilityEnabled && + !user?.is_stake_eligible && + isStakeProtectedRoute + ) { + return ; + } + + return children; +} diff --git a/packages/apps/human-app/frontend/src/modules/worker/services/exchangeApiKeys.service.ts b/packages/apps/human-app/frontend/src/modules/worker/services/exchangeApiKeys.service.ts new file mode 100644 index 0000000000..41db9404e2 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/services/exchangeApiKeys.service.ts @@ -0,0 +1,46 @@ +import { authorizedHumanAppApiClient } from '@/api'; + +interface ExchangeApiKey { + api_key: string; + exchange_name: string; +} + +interface Exchange { + name: string; + display_name: string; +} + +async function getSupportedExchanges(): Promise { + const response = await authorizedHumanAppApiClient.get( + '/exchange-api-keys/supported-exchanges' + ); + return response || []; +} + +async function getExchangeApiKeys(): Promise { + const response = + await authorizedHumanAppApiClient.get('/exchange-api-keys'); + return response || null; +} + +async function enrollExchangeApiKeys(data: { + exchange: string; + apiKey: string; + secretKey: string; +}): Promise { + const { exchange, ...body } = data; + await authorizedHumanAppApiClient.post(`/exchange-api-keys/${exchange}`, { + body, + }); +} + +async function deleteExchangeApiKeys(): Promise { + await authorizedHumanAppApiClient.delete('/exchange-api-keys'); +} + +export { + enrollExchangeApiKeys, + getExchangeApiKeys, + deleteExchangeApiKeys, + getSupportedExchanges, +}; diff --git a/packages/apps/human-app/frontend/src/modules/worker/services/staking.service.ts b/packages/apps/human-app/frontend/src/modules/worker/services/staking.service.ts new file mode 100644 index 0000000000..d4a38a65b3 --- /dev/null +++ b/packages/apps/human-app/frontend/src/modules/worker/services/staking.service.ts @@ -0,0 +1,16 @@ +import { authorizedHumanAppApiClient } from '@/api'; + +interface StakeSummary { + exchange_stake: string; + exchange_error?: string; + on_chain_stake: string; + on_chain_error?: string; +} + +async function getStakingSummary(): Promise { + const response = + await authorizedHumanAppApiClient.get('/staking/summary'); + return response || null; +} + +export { getStakingSummary }; diff --git a/packages/apps/human-app/frontend/src/router/components/drawer-menu-items/drawer-menu-items-worker.tsx b/packages/apps/human-app/frontend/src/router/components/drawer-menu-items/drawer-menu-items-worker.tsx index 427bba124b..5c39359e16 100644 --- a/packages/apps/human-app/frontend/src/router/components/drawer-menu-items/drawer-menu-items-worker.tsx +++ b/packages/apps/human-app/frontend/src/router/components/drawer-menu-items/drawer-menu-items-worker.tsx @@ -9,14 +9,21 @@ import type { UserData } from '@/modules/auth/context/auth-context'; import { routerPaths } from '@/router/router-paths'; import { KycStatus } from '@/modules/worker/profile/types'; import { type MenuItem } from '../layout/protected'; +import { UiConfig } from '@/shared/services/ui-config.service'; -export const workerDrawerTopMenuItems = (user: UserData | null): MenuItem[] => { +export const workerDrawerTopMenuItems = ( + user: UserData | null, + uiConfig: UiConfig | undefined +): MenuItem[] => { return [ { label: t('components.DrawerNavigation.jobs'), icon: , link: routerPaths.worker.jobsDiscovery, - disabled: !user?.wallet_address || user.kyc_status !== KycStatus.APPROVED, + disabled: + !user?.wallet_address || + (uiConfig?.stakingEligibilityEnabled && !user?.is_stake_eligible) || + user.kyc_status !== KycStatus.APPROVED, }, ]; }; diff --git a/packages/apps/human-app/frontend/src/router/router.tsx b/packages/apps/human-app/frontend/src/router/router.tsx index b22c8052d8..0d27ce4c46 100644 --- a/packages/apps/human-app/frontend/src/router/router.tsx +++ b/packages/apps/human-app/frontend/src/router/router.tsx @@ -20,9 +20,12 @@ import { workerDrawerBottomMenuItems, workerDrawerTopMenuItems, } from './components'; +import { RequireStake } from '@/modules/worker/providers/require-stake'; +import { useUiConfig } from '@/shared/providers/ui-config-provider'; export function Router() { const { user } = useAuth(); + const { uiConfig } = useUiConfig(); const handleSignOut = () => { browserAuthProvider.signOut({ @@ -57,22 +60,24 @@ export function Router() { - ( - - )} - renderHCaptchaStatisticsDrawer={(isOpen) => ( - - )} - renderGovernanceBanner - /> + + ( + + )} + renderHCaptchaStatisticsDrawer={(isOpen) => ( + + )} + renderGovernanceBanner + /> + } key={routerProps.path} diff --git a/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx b/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx index 4a8c8ada84..ba1cb12ec9 100644 --- a/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx +++ b/packages/apps/human-app/frontend/src/shared/components/data-entry/input.tsx @@ -5,10 +5,8 @@ import { Typography } from '@mui/material'; import { type InputMask } from '@/shared/components/data-entry/input-masks'; import { useColorMode } from '@/shared/contexts/color-mode'; -export interface InputProps extends Omit< - TextFieldProps, - 'name' | 'error' | 'helperText' -> { +type OmittedProps = Omit; +export interface InputProps extends OmittedProps { name: string; label?: string; autoComplete?: string; diff --git a/packages/apps/human-app/frontend/src/shared/components/ui/icons.tsx b/packages/apps/human-app/frontend/src/shared/components/ui/icons.tsx index 25681beef6..f58d0b3cba 100644 --- a/packages/apps/human-app/frontend/src/shared/components/ui/icons.tsx +++ b/packages/apps/human-app/frontend/src/shared/components/ui/icons.tsx @@ -39,6 +39,12 @@ import MoonIconLight from '@/assets/icons/moon.svg'; import { useColorMode } from '@/shared/contexts/color-mode'; import WorkHeaderDark from '@/assets/icons-dark-mode/work-header.svg'; import WorkHeaderLight from '@/assets/icons/work-header.svg'; +import CopyIconLight from '@/assets/icons/content-copy.svg'; +import CopyIconDark from '@/assets/icons-dark-mode/content-copy.svg'; +import EditIconLight from '@/assets/icons/edit-icon.svg'; +import EditIconDark from '@/assets/icons-dark-mode/edit-icon.svg'; +import DeleteIconLight from '@/assets/icons/delete-icon.svg'; +import DeleteIconDark from '@/assets/icons-dark-mode/delete-icon.svg'; function HomepageLogoIcon() { const { isDarkMode } = useColorMode(); @@ -124,6 +130,18 @@ function MoonIcon() { const { isDarkMode } = useColorMode(); return isDarkMode ? : ; } +function CopyIcon() { + const { isDarkMode } = useColorMode(); + return isDarkMode ? : ; +} +function EditIcon() { + const { isDarkMode } = useColorMode(); + return isDarkMode ? : ; +} +function DeleteIcon() { + const { isDarkMode } = useColorMode(); + return isDarkMode ? : ; +} export { HomepageLogoIcon, @@ -148,4 +166,7 @@ export { SunIcon, MoonIcon, WorkHeaderIcon, + CopyIcon, + EditIcon, + DeleteIcon, }; diff --git a/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx b/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx index 16958d5dc7..7a73af61b8 100644 --- a/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx +++ b/packages/apps/human-app/frontend/src/shared/components/ui/modal/global-modal.tsx @@ -1,30 +1,49 @@ -import { DialogContent } from '@mui/material'; -import DialogMui from '@mui/material/Dialog'; +import { DialogContent, IconButton, Dialog } from '@mui/material'; import { useModal } from '../../../contexts/modal-context'; -import { ModalHeader } from './modal-header'; +import CloseIcon from '@mui/icons-material/Close'; export function GlobalModal() { - const { open, closeModal, showCloseButton, content, onTransitionExited } = - useModal(); + const { + open, + closeModal, + showCloseButton, + disableClose, + content, + onTransitionExited, + } = useModal(); return ( - - - {content} - + {showCloseButton && ( + + + + )} + + {content} + + ); } diff --git a/packages/apps/human-app/frontend/src/shared/components/ui/modal/modal-header.tsx b/packages/apps/human-app/frontend/src/shared/components/ui/modal/modal-header.tsx deleted file mode 100644 index 423a295366..0000000000 --- a/packages/apps/human-app/frontend/src/shared/components/ui/modal/modal-header.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import Grid from '@mui/material/Grid'; -import Button from '@mui/material/Button'; -import { Typography } from '@mui/material'; -import { useTranslation } from 'react-i18next'; - -interface ModalHeaderElementProps { - isVisible: boolean; - onClick: () => void; -} - -interface ModalHeaderProps { - closeButton?: ModalHeaderElementProps; -} - -export function ModalHeader({ closeButton }: Readonly) { - const { t } = useTranslation(); - return ( - - - {closeButton?.isVisible && ( - - - - )} - - - ); -} diff --git a/packages/apps/human-app/frontend/src/shared/contexts/modal-context.tsx b/packages/apps/human-app/frontend/src/shared/contexts/modal-context.tsx index 276c85be50..daf1e32eab 100644 --- a/packages/apps/human-app/frontend/src/shared/contexts/modal-context.tsx +++ b/packages/apps/human-app/frontend/src/shared/contexts/modal-context.tsx @@ -10,9 +10,11 @@ interface ModalContextType { open: boolean; content: React.ReactNode; showCloseButton: boolean; + disableClose: boolean; openModal: ({ content, showCloseButton }: OpenModalProps) => void; closeModal: () => void; onTransitionExited: () => void; + setDisableClose: (disable: boolean) => void; } interface OpenModalProps { @@ -28,6 +30,7 @@ export function ModalProvider({ const [open, setOpen] = useState(false); const [content, setContent] = useState(null); const [showCloseButton, setShowCloseButton] = useState(true); + const [disableClose, setDisableClose] = useState(false); const openModal = useCallback( ({ @@ -36,14 +39,16 @@ export function ModalProvider({ }: OpenModalProps) => { setContent(_modalContent); setShowCloseButton(_showCloseButton ?? showCloseButton); + setDisableClose(false); setOpen(true); }, [showCloseButton] ); const closeModal = useCallback(() => { + if (disableClose) return; setOpen(false); - }, []); + }, [disableClose]); const onTransitionExited = useCallback(() => { setContent(null); @@ -54,11 +59,21 @@ export function ModalProvider({ open, content, showCloseButton, + disableClose, openModal, closeModal, onTransitionExited, + setDisableClose, }), - [open, content, showCloseButton, openModal, closeModal, onTransitionExited] + [ + open, + content, + showCloseButton, + disableClose, + openModal, + closeModal, + onTransitionExited, + ] ); return ( diff --git a/packages/apps/human-app/frontend/src/shared/env.ts b/packages/apps/human-app/frontend/src/shared/env.ts index b442081d05..3be4fb921a 100644 --- a/packages/apps/human-app/frontend/src/shared/env.ts +++ b/packages/apps/human-app/frontend/src/shared/env.ts @@ -5,6 +5,7 @@ const envSchema = z.object({ VITE_PRIVACY_POLICY_URL: z.string(), VITE_TERMS_OF_SERVICE_URL: z.string(), VITE_HUMAN_PROTOCOL_URL: z.string(), + VITE_STAKING_DASHBOARD_URL: z.string(), VITE_NAVBAR__LINK__PROTOCOL_URL: z.string(), VITE_NAVBAR__LINK__HOW_IT_WORK_URL: z.string(), VITE_HUMAN_SUPPORT_EMAIL: z.string(), diff --git a/packages/apps/human-app/frontend/src/shared/i18n/en.json b/packages/apps/human-app/frontend/src/shared/i18n/en.json index 91bae6249a..951559cb63 100644 --- a/packages/apps/human-app/frontend/src/shared/i18n/en.json +++ b/packages/apps/human-app/frontend/src/shared/i18n/en.json @@ -90,7 +90,8 @@ "pageCardError": { "reload": "Reload", "goHome": "Home Page" - } + }, + "copyToClipboard": "Copied" }, "homepage": { "humanApp": "HUMAN App", @@ -225,6 +226,47 @@ "review": "Under Review", "expired": "Expired", "abandoned": "Abandoned" + }, + "stakingStatusValues": { + "staked": "Staked", + "error": "Error", + "notStaked": "Not Staked" + }, + "stakingInfo": { + "promptShort": "Before you can start earning on the HUMAN App, you'll need to stake HMT.", + "prompt": "Before you can start earning on the HUMAN App, you’ll need to stake HMT. You can stake directly on our Staking Dashboard, or connect your API key having minimum balance of {{amount}} HMT in your exchange account to stake automatically via API KEY.", + "stakeHmt": "Stake HMT", + "stakingInfoValue": "Staking Info Value", + "stakedAmount": "Staked amount", + "readMore": "Read more", + "readLess": "Read less" + }, + "apiKeyData": { + "apiKey": "API KEY", + "exchange": "Exchange", + "apiSecret": "API Secret", + "apiKeyConnected": "Connected", + "apiKeyNotConnected": "Not connected", + "cancel": "Cancel", + "error": "Error", + "close": "Close", + "edit": "Edit", + "tryAgain": "Try Again", + "connectYourApiKey": "Connect your API KEY", + "connectApiKey": "Connect API KEY", + "connectSuccess": "You have successfully connected your API key", + "connectError": "Failed to connect API key.", + "editSuccess": "You have successfully edited your API key", + "editError": "Failed to edit API key.", + "deleteKeySuccess": "You have successfully deleted your API key", + "deleteKeyError": "Failed to delete API key.", + "modalDescription": "To stake HMT using your exchange balance, connect your exchange account by adding your API key and secret. Your credentials are encrypted and securely stored.", + "modalFooterAgreement": "By connecting your API KEY, you agree to HUMAN Protocol Terms of Service and consent to its Privacy Policy.", + "deleteApiKey": "Delete API KEY", + "deleteApiKeyConfirmation": "Are you sure you want to delete your API key?", + "deleteApiKeyDescription": "You can only solve jobs in the HUMAN App if you have staked HMT.", + "editApiKey": "Edit API KEY", + "saveChanges": "Save Changes" } }, "oraclesTable": { diff --git a/packages/apps/human-app/frontend/src/shared/providers/ui-config-provider.tsx b/packages/apps/human-app/frontend/src/shared/providers/ui-config-provider.tsx new file mode 100644 index 0000000000..5f23cd7d49 --- /dev/null +++ b/packages/apps/human-app/frontend/src/shared/providers/ui-config-provider.tsx @@ -0,0 +1,44 @@ +import React, { createContext, useContext, useMemo } from 'react'; +import { useGetUiConfig } from '../hooks/use-get-ui-config'; +import { UiConfig } from '../services/ui-config.service'; + +interface UiConfigContextType { + uiConfig: UiConfig | undefined; + isUiConfigLoading: boolean; + isUiConfigError: boolean; + error: Error | null; +} + +const UiConfigContext = createContext( + undefined +); + +export function UiConfigProvider({ + children, +}: Readonly<{ children: React.ReactNode }>) { + const { data, isLoading, error, isError } = useGetUiConfig(); + + const contextValue = useMemo( + () => ({ + uiConfig: data, + isUiConfigLoading: isLoading, + isUiConfigError: isError, + error, + }), + [data, isLoading, isError, error] + ); + + return ( + + {children} + + ); +} + +export const useUiConfig = () => { + const context = useContext(UiConfigContext); + if (!context) { + throw new Error('useUiConfig must be used within a UiConfigProvider'); + } + return context; +}; diff --git a/packages/apps/human-app/frontend/src/shared/services/ui-config.service.ts b/packages/apps/human-app/frontend/src/shared/services/ui-config.service.ts index 4343540456..5103cc92c3 100644 --- a/packages/apps/human-app/frontend/src/shared/services/ui-config.service.ts +++ b/packages/apps/human-app/frontend/src/shared/services/ui-config.service.ts @@ -7,9 +7,11 @@ const apiPaths = { const uiConfigSchema = z.object({ chainIdsEnabled: z.array(z.number()), + stakingEligibilityEnabled: z.boolean().prefault(false), + minThreshold: z.string(), }); -type UiConfig = z.infer; +export type UiConfig = z.infer; async function getUiConfig() { try { diff --git a/packages/apps/human-app/frontend/src/shared/styles/theme.ts b/packages/apps/human-app/frontend/src/shared/styles/theme.ts index 871d14719e..44a04ae421 100644 --- a/packages/apps/human-app/frontend/src/shared/styles/theme.ts +++ b/packages/apps/human-app/frontend/src/shared/styles/theme.ts @@ -140,6 +140,13 @@ export const theme: ThemeOptions = { }, }, }, + MuiSkeleton: { + styleOverrides: { + root: { + transform: 'scale(1,1)', + }, + }, + }, }, breakpoints: { values: { diff --git a/packages/apps/human-app/frontend/vite.config.mjs b/packages/apps/human-app/frontend/vite.config.mjs index 40943d146b..436d6c86a8 100644 --- a/packages/apps/human-app/frontend/vite.config.mjs +++ b/packages/apps/human-app/frontend/vite.config.mjs @@ -22,6 +22,9 @@ const config = defineConfig({ }, build: { target: 'esnext', + commonjsOptions: { + include: [/core/, /human-protocol-sdk/, /node_modules/], + }, }, server: { host: '127.0.0.1', @@ -29,12 +32,14 @@ const config = defineConfig({ }, optimizeDeps: { include: [ + '@human-protocol/sdk', '@mui/material', '@emotion/react', '@emotion/styled', '@mui/material/Tooltip', '@mui/material/Paper', ], + force: true, }, }); diff --git a/packages/apps/human-app/server/src/app.module.ts b/packages/apps/human-app/server/src/app.module.ts index 529154b0ed..6de9bbd087 100644 --- a/packages/apps/human-app/server/src/app.module.ts +++ b/packages/apps/human-app/server/src/app.module.ts @@ -58,6 +58,10 @@ import { OperatorController } from './modules/user-operator/operator.controller' import { OperatorModule } from './modules/user-operator/operator.module'; import { WorkerController } from './modules/user-worker/worker.controller'; import { WorkerModule } from './modules/user-worker/worker.module'; +import { ExchangeApiKeysModule } from './modules/exchange-api-keys/exchange-api-keys.module'; +import { ExchangeApiKeysController } from './modules/exchange-api-keys/exchange-api-keys.controller'; +import { StakingController } from './modules/staking/staking.controller'; +import { StakingModule } from './modules/staking/staking.module'; const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false'); @@ -147,6 +151,8 @@ const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false'); NDAModule, AbuseModule, GovernanceModule, + ExchangeApiKeysModule, + StakingModule, ], controllers: [ AppController, @@ -162,6 +168,8 @@ const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false'); NDAController, AbuseController, GovernanceController, + ExchangeApiKeysController, + StakingController, ], exports: [HttpModule], providers: [ diff --git a/packages/apps/human-app/server/src/common/config/gateway-config.service.ts b/packages/apps/human-app/server/src/common/config/gateway-config.service.ts index 7f7c548fb2..0dbbb0c2cb 100644 --- a/packages/apps/human-app/server/src/common/config/gateway-config.service.ts +++ b/packages/apps/human-app/server/src/common/config/gateway-config.service.ts @@ -141,6 +141,36 @@ export class GatewayConfigService { method: HttpMethod.GET, headers: this.JSON_HEADER, }, + [ReputationOracleEndpoints.EXCHANGE_API_KEYS_ENROLL]: { + endpoint: '/exchange-api-keys', + method: HttpMethod.POST, + headers: this.JSON_HEADER, + }, + [ReputationOracleEndpoints.EXCHANGE_API_KEYS_DELETE]: { + endpoint: '/exchange-api-keys', + method: HttpMethod.DELETE, + headers: this.JSON_HEADER, + }, + [ReputationOracleEndpoints.EXCHANGE_API_KEYS_RETRIEVE]: { + endpoint: '/exchange-api-keys', + method: HttpMethod.GET, + headers: this.JSON_HEADER, + }, + [ReputationOracleEndpoints.EXCHANGE_API_KEYS_SUPPORTED_EXCHANGES]: { + endpoint: '/exchange-api-keys/supported', + method: HttpMethod.GET, + headers: this.JSON_HEADER, + }, + [ReputationOracleEndpoints.STAKE_SUMMARY]: { + endpoint: '/staking/summary', + method: HttpMethod.GET, + headers: this.JSON_HEADER, + }, + [ReputationOracleEndpoints.STAKE_CONFIG]: { + endpoint: '/staking/config', + method: HttpMethod.GET, + headers: this.JSON_HEADER, + }, } as Record, }, [ExternalApiName.HCAPTCHA_LABELING_STATS]: { diff --git a/packages/apps/human-app/server/src/common/enums/http-method.ts b/packages/apps/human-app/server/src/common/enums/http-method.ts index 5a3bbf6de1..4dfcef38b9 100644 --- a/packages/apps/human-app/server/src/common/enums/http-method.ts +++ b/packages/apps/human-app/server/src/common/enums/http-method.ts @@ -1,4 +1,5 @@ export enum HttpMethod { GET = 'GET', POST = 'POST', + DELETE = 'DELETE', } diff --git a/packages/apps/human-app/server/src/common/enums/reputation-oracle-endpoints.ts b/packages/apps/human-app/server/src/common/enums/reputation-oracle-endpoints.ts index bedd90d15d..63cc216389 100644 --- a/packages/apps/human-app/server/src/common/enums/reputation-oracle-endpoints.ts +++ b/packages/apps/human-app/server/src/common/enums/reputation-oracle-endpoints.ts @@ -22,6 +22,12 @@ export enum ReputationOracleEndpoints { SIGN_NDA = 'sign_nda', REPORT_ABUSE = 'report_abuse', GET_ABUSE_REPORTS = 'get_abuse_reports', + EXCHANGE_API_KEYS_ENROLL = 'exchange_api_keys_enroll', + EXCHANGE_API_KEYS_DELETE = 'exchange_api_keys_delete', + EXCHANGE_API_KEYS_RETRIEVE = 'exchange_api_keys_retrieve', + EXCHANGE_API_KEYS_SUPPORTED_EXCHANGES = 'exchange_api_keys_supported_exchanges', + STAKE_SUMMARY = 'stake_summary', + STAKE_CONFIG = 'stake_config', } export enum HCaptchaLabelingStatsEndpoints { USER_STATS = 'user_stats', diff --git a/packages/apps/human-app/server/src/common/guards/strategy/jwt.http.ts b/packages/apps/human-app/server/src/common/guards/strategy/jwt.http.ts index 1a06cd60ee..5d79c29c28 100644 --- a/packages/apps/human-app/server/src/common/guards/strategy/jwt.http.ts +++ b/packages/apps/human-app/server/src/common/guards/strategy/jwt.http.ts @@ -44,6 +44,7 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { status: string; wallet_address: string; reputation_network: string; + is_stake_eligible?: boolean; qualifications?: string[]; site_key?: string; email?: string; @@ -58,6 +59,7 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') { wallet_address: payload.wallet_address, status: payload.status, reputation_network: payload.reputation_network, + is_stake_eligible: payload.is_stake_eligible, qualifications: payload.qualifications, site_key: payload.site_key, email: payload.email, diff --git a/packages/apps/human-app/server/src/common/utils/jwt-token.model.ts b/packages/apps/human-app/server/src/common/utils/jwt-token.model.ts index 85da60b3c1..a0175c642d 100644 --- a/packages/apps/human-app/server/src/common/utils/jwt-token.model.ts +++ b/packages/apps/human-app/server/src/common/utils/jwt-token.model.ts @@ -10,6 +10,8 @@ export class JwtUserData { @AutoMap() reputation_network: string; @AutoMap() + is_stake_eligible?: boolean; + @AutoMap() email?: string; @AutoMap() qualifications?: string[]; diff --git a/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.gateway.ts b/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.gateway.ts index adebda27cf..618833409a 100644 --- a/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.gateway.ts @@ -95,6 +95,17 @@ import { ReportAbuseParams, ReportedAbuseResponse, } from '../../modules/abuse/model/abuse.model'; +import { HttpMethod } from '../../common/enums/http-method'; +import { + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysData, + RetrieveExchangeApiKeysResponse, + SupportedExchangeResponse, +} from '../../modules/exchange-api-keys/model/exchange-api-keys.model'; +import { + StakeConfigResponse, + StakeSummaryResponse, +} from '../../modules/staking/model/staking.model'; @Injectable() export class ReputationOracleGateway { @@ -136,6 +147,77 @@ export class ReputationOracleGateway { const response = await lastValueFrom(this.httpService.request(options)); return response.data as T; } + + async enrollExchangeApiKeys( + command: EnrollExchangeApiKeysCommand, + ): Promise<{ id: number }> { + const enrollExchangeApiKeysData = this.mapper.map( + command, + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysData, + ); + const options = this.getEndpointOptions( + ReputationOracleEndpoints.EXCHANGE_API_KEYS_ENROLL, + enrollExchangeApiKeysData, + command.token, + ); + options.url = `${options.url}/${command.exchangeName}`; + return this.handleRequestToReputationOracle<{ id: number }>(options); + } + + async deleteExchangeApiKeys(token: string) { + const options = this.getEndpointOptions( + ReputationOracleEndpoints.EXCHANGE_API_KEYS_DELETE, + undefined, + token, + ); + options.method = HttpMethod.DELETE; + return this.handleRequestToReputationOracle(options); + } + + async retrieveExchangeApiKeys( + token: string, + ): Promise { + const options = this.getEndpointOptions( + ReputationOracleEndpoints.EXCHANGE_API_KEYS_RETRIEVE, + undefined, + token, + ); + return this.handleRequestToReputationOracle( + options, + ); + } + + async getStakeSummary(token: string): Promise { + const options = this.getEndpointOptions( + ReputationOracleEndpoints.STAKE_SUMMARY, + undefined, + token, + ); + return this.handleRequestToReputationOracle(options); + } + + async getStakeConfig(): Promise { + const options = this.getEndpointOptions( + ReputationOracleEndpoints.STAKE_CONFIG, + undefined, + ); + return this.handleRequestToReputationOracle(options); + } + + async supportedExchanges( + token: string, + ): Promise { + const options = this.getEndpointOptions( + ReputationOracleEndpoints.EXCHANGE_API_KEYS_SUPPORTED_EXCHANGES, + undefined, + token, + ); + return this.handleRequestToReputationOracle( + options, + ); + } + async sendWorkerSignup(command: SignupWorkerCommand): Promise { const signupWorkerData = this.mapper.map( command, diff --git a/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.mapper.profile.ts b/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.mapper.profile.ts index 1c147e2833..3488762b01 100644 --- a/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.mapper.profile.ts +++ b/packages/apps/human-app/server/src/integrations/reputation-oracle/reputation-oracle.mapper.profile.ts @@ -62,6 +62,10 @@ import { ReportAbuseData, ReportAbuseParams, } from '../../modules/abuse/model/abuse.model'; +import { + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysData, +} from '../../modules/exchange-api-keys/model/exchange-api-keys.model'; @Injectable() export class ReputationOracleProfile extends AutomapperProfile { @@ -166,6 +170,15 @@ export class ReputationOracleProfile extends AutomapperProfile { destination: new SnakeCaseNamingConvention(), }), ); + createMap( + mapper, + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysData, + namingConventions({ + source: new CamelCaseNamingConvention(), + destination: new SnakeCaseNamingConvention(), + }), + ); }; } } diff --git a/packages/apps/human-app/server/src/main.ts b/packages/apps/human-app/server/src/main.ts index 6f1ea1f0dd..726bd19b9b 100644 --- a/packages/apps/human-app/server/src/main.ts +++ b/packages/apps/human-app/server/src/main.ts @@ -19,7 +19,7 @@ async function bootstrap() { if (envConfigService.isCorsEnabled) { app.enableCors({ origin: envConfigService.corsEnabledOrigin, - methods: ['GET', 'POST', 'OPTIONS', 'PUT'], + methods: ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE'], allowedHeaders: envConfigService.corsAllowedHeaders, }); } diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts new file mode 100644 index 0000000000..efb605dfa9 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts @@ -0,0 +1,83 @@ +import { + Body, + Controller, + Delete, + Get, + HttpCode, + Param, + Post, + Request, +} from '@nestjs/common'; +import { + ApiBearerAuth, + ApiBody, + ApiOperation, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; +import { RequestWithUser } from '../../common/interfaces/jwt'; +import { ExchangeApiKeysService } from '../../modules/exchange-api-keys/exchange-api-keys.service'; +import { InjectMapper } from '@automapper/nestjs'; +import { Mapper } from '@automapper/core'; +import { + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysDto, + RetrieveExchangeApiKeysResponse, + SupportedExchangeResponse, +} from './model/exchange-api-keys.model'; + +@ApiTags('Exchange-Api-Keys') +@ApiBearerAuth() +@Controller('/exchange-api-keys') +export class ExchangeApiKeysController { + constructor( + private readonly service: ExchangeApiKeysService, + @InjectMapper() private readonly mapper: Mapper, + ) {} + + @ApiOperation({ summary: 'Enroll API keys for exchange' }) + @ApiBody({ type: EnrollExchangeApiKeysDto }) + @ApiResponse({ status: 200, description: 'Exchange API keys enrolled' }) + @HttpCode(200) + @Post('/:exchange_name') + async enroll( + @Param('exchange_name') exchangeName: string, + @Body() dto: EnrollExchangeApiKeysDto, + @Request() req: RequestWithUser, + ): Promise<{ id: number }> { + const command = this.mapper.map( + dto, + EnrollExchangeApiKeysDto, + EnrollExchangeApiKeysCommand, + ); + command.token = req.token; + command.exchangeName = exchangeName; + return this.service.enroll(command); + } + + @ApiOperation({ summary: 'Delete API keys for exchange' }) + @ApiResponse({ status: 204, description: 'Exchange API keys deleted' }) + @HttpCode(204) + @Delete('/') + async delete(@Request() req: RequestWithUser): Promise { + await this.service.delete(req.token); + } + + @ApiOperation({ + summary: 'Retrieve API keys for exchange', + }) + @Get('/') + async retrieve( + @Request() req: RequestWithUser, + ): Promise { + return this.service.retrieve(req.token); + } + + @ApiOperation({ summary: 'Get supported exchanges' }) + @Get('/supported-exchanges') + async getSupportedExchanges( + @Request() req: RequestWithUser, + ): Promise { + return this.service.getSupportedExchanges(req.token); + } +} diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.mapper.profile.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.mapper.profile.ts new file mode 100644 index 0000000000..5f65c8f475 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.mapper.profile.ts @@ -0,0 +1,20 @@ +import { Mapper, createMap } from '@automapper/core'; +import { AutomapperProfile, InjectMapper } from '@automapper/nestjs'; +import { Injectable } from '@nestjs/common'; +import { + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysDto, +} from './model/exchange-api-keys.model'; + +@Injectable() +export class ExchangeApiKeysProfile extends AutomapperProfile { + constructor(@InjectMapper() mapper: Mapper) { + super(mapper); + } + + override get profile() { + return (mapper: Mapper) => { + createMap(mapper, EnrollExchangeApiKeysDto, EnrollExchangeApiKeysCommand); + }; + } +} diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts new file mode 100644 index 0000000000..3b6d627810 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { ExchangeApiKeysController } from '../../modules/exchange-api-keys/exchange-api-keys.controller'; +import { ExchangeApiKeysService } from '../../modules/exchange-api-keys/exchange-api-keys.service'; +import { ReputationOracleModule } from '../../integrations/reputation-oracle/reputation-oracle.module'; +import { ExchangeApiKeysProfile } from './exchange-api-keys.mapper.profile'; + +@Module({ + imports: [ReputationOracleModule], + controllers: [ExchangeApiKeysController], + providers: [ExchangeApiKeysService, ExchangeApiKeysProfile], + exports: [ExchangeApiKeysService], +}) +export class ExchangeApiKeysModule {} diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts new file mode 100644 index 0000000000..712335441b --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@nestjs/common'; +import { ReputationOracleGateway } from '../../integrations/reputation-oracle/reputation-oracle.gateway'; +import { + EnrollExchangeApiKeysCommand, + RetrieveExchangeApiKeysResponse, + SupportedExchangeResponse, +} from './model/exchange-api-keys.model'; + +@Injectable() +export class ExchangeApiKeysService { + constructor(private readonly reputationOracle: ReputationOracleGateway) {} + + enroll(command: EnrollExchangeApiKeysCommand): Promise<{ id: number }> { + return this.reputationOracle.enrollExchangeApiKeys(command); + } + + delete(token: string): Promise { + return this.reputationOracle.deleteExchangeApiKeys(token); + } + + retrieve(token: string): Promise { + return this.reputationOracle.retrieveExchangeApiKeys(token); + } + + getSupportedExchanges(token: string): Promise { + return this.reputationOracle.supportedExchanges(token); + } +} diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/model/exchange-api-keys.model.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/model/exchange-api-keys.model.ts new file mode 100644 index 0000000000..f07c049e26 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/model/exchange-api-keys.model.ts @@ -0,0 +1,44 @@ +import { AutoMap } from '@automapper/classes'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; + +export class EnrollExchangeApiKeysDto { + @AutoMap() + @IsString() + @ApiProperty() + apiKey: string; + + @AutoMap() + @IsString() + @ApiProperty() + secretKey: string; +} + +export class EnrollExchangeApiKeysCommand { + @AutoMap() + apiKey: string; + @AutoMap() + secretKey: string; + token: string; + exchangeName: string; +} + +export class EnrollExchangeApiKeysData { + @AutoMap() + apiKey: string; + @AutoMap() + secretKey: string; +} + +export class RetrieveExchangeApiKeysResponse { + apiKey: string; + exchangeName: string; +} + +export class SupportedExchangeResponse { + @ApiProperty() + name: string; + + @ApiProperty() + displayName: string; +} diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.controller.spec.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.controller.spec.ts new file mode 100644 index 0000000000..e298642428 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.controller.spec.ts @@ -0,0 +1,96 @@ +import { classes } from '@automapper/classes'; +import { AutomapperModule } from '@automapper/nestjs'; +import { Test, TestingModule } from '@nestjs/testing'; +import { RequestWithUser } from '../../../common/interfaces/jwt'; +import { ExchangeApiKeysController } from '../exchange-api-keys.controller'; +import { ExchangeApiKeysService } from '../exchange-api-keys.service'; +import { + enrollExchangeApiKeysCommandFixture, + enrollExchangeApiKeysDtoFixture, + enrollExchangeApiKeysResponseFixture, + EXCHANGE_NAME, + retrieveExchangeApiKeysResponseFixture, + TOKEN, +} from './exchange-api-keys.fixtures'; +import { exchangeApiKeysServiceMock } from './exchange-api-keys.service.mock'; +import { ExchangeApiKeysProfile } from '../exchange-api-keys.mapper.profile'; + +describe('ExchangeApiKeysController', () => { + let controller: ExchangeApiKeysController; + let service: ExchangeApiKeysService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ExchangeApiKeysController], + imports: [ + AutomapperModule.forRoot({ + strategyInitializer: classes(), + }), + ], + providers: [ + ExchangeApiKeysService, + ExchangeApiKeysProfile, + { + provide: ExchangeApiKeysService, + useValue: exchangeApiKeysServiceMock, + }, + ], + }) + .overrideProvider(ExchangeApiKeysService) + .useValue(exchangeApiKeysServiceMock) + .compile(); + + controller = module.get( + ExchangeApiKeysController, + ); + service = module.get(ExchangeApiKeysService); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); + + describe('enroll', () => { + it('should call service.enroll with mapped command and return id', async () => { + const req: RequestWithUser = { token: TOKEN } as RequestWithUser; + const result = await controller.enroll( + EXCHANGE_NAME, + enrollExchangeApiKeysDtoFixture, + req, + ); + expect(service.enroll).toHaveBeenCalledWith( + enrollExchangeApiKeysCommandFixture, + ); + expect(result).toEqual(enrollExchangeApiKeysResponseFixture); + }); + }); + + describe('delete', () => { + it('should call service.delete with token', async () => { + const req: RequestWithUser = { token: TOKEN } as RequestWithUser; + const result = await controller.delete(req); + expect(service.delete).toHaveBeenCalledWith(TOKEN); + expect(result).toEqual(undefined); + }); + }); + + describe('retrieve', () => { + it('should call service.retrieve with token and return response', async () => { + const req: RequestWithUser = { token: TOKEN } as RequestWithUser; + const result = await controller.retrieve(req); + expect(service.retrieve).toHaveBeenCalledWith(TOKEN); + expect(result).toEqual(retrieveExchangeApiKeysResponseFixture); + }); + }); + + describe('getSupportedExchanges', () => { + it('should call service.getSupportedExchanges with token and return response', async () => { + const req: RequestWithUser = { token: TOKEN } as RequestWithUser; + const result = await controller.getSupportedExchanges(req); + expect(service.getSupportedExchanges).toHaveBeenCalledWith(TOKEN); + expect(result).toEqual( + exchangeApiKeysServiceMock.getSupportedExchanges(TOKEN), + ); + }); + }); +}); diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.fixtures.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.fixtures.ts new file mode 100644 index 0000000000..8cfda1ab77 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.fixtures.ts @@ -0,0 +1,45 @@ +import { + EnrollExchangeApiKeysCommand, + EnrollExchangeApiKeysDto, + RetrieveExchangeApiKeysResponse, +} from '../model/exchange-api-keys.model'; + +export const EXCHANGE_NAME = 'mexc'; +export const TOKEN = 'test_user_token'; +export const API_KEY = 'test_api_key'; +export const API_SECRET = 'test_api_secret'; +export const ID = 123; + +export const enrollExchangeApiKeysDtoFixture: EnrollExchangeApiKeysDto = { + apiKey: API_KEY, + secretKey: API_SECRET, +}; + +export const enrollExchangeApiKeysCommandFixture: EnrollExchangeApiKeysCommand = + { + apiKey: API_KEY, + secretKey: API_SECRET, + token: TOKEN, + exchangeName: EXCHANGE_NAME, + }; + +export const enrollExchangeApiKeysResponseFixture = { + id: ID, +}; + +export const retrieveExchangeApiKeysResponseFixture: RetrieveExchangeApiKeysResponse = + { + apiKey: API_KEY, + exchangeName: EXCHANGE_NAME, + }; + +export const supportedExchangesResponseFixture = [ + { + name: 'mexc', + displayName: 'MEXC Global', + }, + { + name: 'gate', + displayName: 'Gate', + }, +]; diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.mock.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.mock.ts new file mode 100644 index 0000000000..357e2142d0 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.mock.ts @@ -0,0 +1,14 @@ +import { + enrollExchangeApiKeysResponseFixture, + retrieveExchangeApiKeysResponseFixture, + supportedExchangesResponseFixture, +} from './exchange-api-keys.fixtures'; + +export const exchangeApiKeysServiceMock = { + enroll: jest.fn().mockReturnValue(enrollExchangeApiKeysResponseFixture), + delete: jest.fn().mockResolvedValue(undefined), + retrieve: jest.fn().mockReturnValue(retrieveExchangeApiKeysResponseFixture), + getSupportedExchanges: jest + .fn() + .mockReturnValue(supportedExchangesResponseFixture), +}; diff --git a/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.spec.ts b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.spec.ts new file mode 100644 index 0000000000..f29868a395 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/exchange-api-keys/spec/exchange-api-keys.service.spec.ts @@ -0,0 +1,89 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ReputationOracleGateway } from '../../../integrations/reputation-oracle/reputation-oracle.gateway'; +import { ExchangeApiKeysService } from '../exchange-api-keys.service'; +import { + enrollExchangeApiKeysCommandFixture, + enrollExchangeApiKeysResponseFixture, + retrieveExchangeApiKeysResponseFixture, + supportedExchangesResponseFixture, + TOKEN, +} from './exchange-api-keys.fixtures'; + +describe('ExchangeApiKeysService', () => { + let service: ExchangeApiKeysService; + let reputationOracleMock: Partial; + + beforeEach(async () => { + reputationOracleMock = { + enrollExchangeApiKeys: jest.fn(), + deleteExchangeApiKeys: jest.fn(), + retrieveExchangeApiKeys: jest.fn(), + getStakeSummary: jest.fn(), + supportedExchanges: jest.fn(), + }; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ExchangeApiKeysService, + { provide: ReputationOracleGateway, useValue: reputationOracleMock }, + ], + }).compile(); + + service = module.get(ExchangeApiKeysService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('enroll', () => { + it('should enroll exchange API keys and return id', async () => { + ( + reputationOracleMock.enrollExchangeApiKeys as jest.Mock + ).mockResolvedValue(enrollExchangeApiKeysResponseFixture); + const result = await service.enroll(enrollExchangeApiKeysCommandFixture); + expect(reputationOracleMock.enrollExchangeApiKeys).toHaveBeenCalledWith( + enrollExchangeApiKeysCommandFixture, + ); + expect(result).toEqual(enrollExchangeApiKeysResponseFixture); + }); + }); + + describe('delete', () => { + it('should delete exchange API keys', async () => { + ( + reputationOracleMock.deleteExchangeApiKeys as jest.Mock + ).mockResolvedValue(undefined); + await service.delete(TOKEN); + expect(reputationOracleMock.deleteExchangeApiKeys).toHaveBeenCalledWith( + TOKEN, + ); + }); + }); + + describe('retrieve', () => { + it('should retrieve exchange API keys', async () => { + ( + reputationOracleMock.retrieveExchangeApiKeys as jest.Mock + ).mockResolvedValue(retrieveExchangeApiKeysResponseFixture); + const result = await service.retrieve(TOKEN); + expect(reputationOracleMock.retrieveExchangeApiKeys).toHaveBeenCalledWith( + TOKEN, + ); + expect(result).toEqual(retrieveExchangeApiKeysResponseFixture); + }); + }); + + describe('getSupportedExchanges', () => { + it('should retrieve supported exchanges', async () => { + (reputationOracleMock.supportedExchanges as jest.Mock).mockResolvedValue( + supportedExchangesResponseFixture, + ); + const result = await service.getSupportedExchanges(TOKEN); + expect(reputationOracleMock.supportedExchanges).toHaveBeenCalledWith( + TOKEN, + ); + expect(result).toEqual(supportedExchangesResponseFixture); + }); + }); +}); diff --git a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts index 3eba428370..bbfa432d1c 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.controller.ts @@ -9,6 +9,7 @@ import { Post, Query, Request, + ForbiddenException, } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { RequestWithUser } from '../../common/interfaces/jwt'; @@ -27,11 +28,16 @@ import { import { ChainId } from '@human-protocol/sdk'; import axios from 'axios'; import { JobStatus } from '../../common/enums/global-common'; +import logger from '../../logger'; @ApiTags('Job-Assignment') @ApiBearerAuth() @Controller('/assignment') export class JobAssignmentController { + private readonly logger = logger.child({ + context: JobAssignmentController.name, + }); + constructor( private readonly service: JobAssignmentService, @InjectMapper() private readonly mapper: Mapper, @@ -46,6 +52,10 @@ export class JobAssignmentController { @Body() jobAssignmentDto: JobAssignmentDto, @Request() req: RequestWithUser, ): Promise { + // Require stake eligibility + if (!req.user?.is_stake_eligible) { + throw new ForbiddenException('Stake requirement not met'); + } // TODO: temporal - THIRSTYFI if (jobAssignmentDto.escrow_address === 'thirstyfi-task') { if (new Date(process.env.THIRSTYFI_TASK_EXPIRATION_DATE!) < new Date()) { @@ -80,8 +90,10 @@ export class JobAssignmentController { expires_at: process.env.THIRSTYFI_TASK_EXPIRATION_DATE ?? '', }; } catch (error) { - // eslint-disable-next-line no-console - console.error(error); + this.logger.error('Failed to assign thirstyfi job', { + userId: req.user.user_id, + error, + }); throw new BadRequestException(error.response.data.error); } } @@ -103,6 +115,16 @@ export class JobAssignmentController { @Query() jobsAssignmentParamsDto: JobsFetchParamsDto, @Request() req: RequestWithUser, ): Promise { + // Require stake eligibility + if (!req.user?.is_stake_eligible) { + return { + page: 0, + page_size: 1, + total_pages: 1, + total_results: 0, + results: [], + }; + } // TODO: temporal - THIRSTYFI if ( jobsAssignmentParamsDto.oracle_address === @@ -166,6 +188,10 @@ export class JobAssignmentController { @Body() dto: ResignJobDto, @Request() req: RequestWithUser, ) { + // Require stake eligibility + if (!req.user?.is_stake_eligible) { + throw new ForbiddenException('Stake requirement not met'); + } const command = this.mapper.map(dto, ResignJobDto, ResignJobCommand); command.token = req.token; return this.service.resignJob(command); @@ -180,6 +206,10 @@ export class JobAssignmentController { @Body() dto: RefreshJobDto, @Request() req: RequestWithUser, ) { + // Require stake eligibility + if (!req.user?.is_stake_eligible) { + throw new ForbiddenException('Stake requirement not met'); + } const command = new JobsFetchParamsCommand(); command.oracleAddress = dto.oracle_address; command.token = req.token; diff --git a/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.controller.spec.ts b/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.controller.spec.ts index ae69ce4e12..f810cce1ca 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/spec/job-assignment.controller.spec.ts @@ -26,6 +26,7 @@ import { TOKEN, } from './job-assignment.fixtures'; import { jobAssignmentServiceMock } from './job-assignment.service.mock'; +import { ForbiddenException } from '@nestjs/common'; const httpServiceMock = { request: jest.fn().mockImplementation((options) => { @@ -77,6 +78,7 @@ describe('JobAssignmentController', () => { const command: JobAssignmentCommand = jobAssignmentCommandFixture; await controller.assignJob(dto, { token: jobAssignmentToken, + user: { is_stake_eligible: true }, } as RequestWithUser); expect(jobAssignmentService.processJobAssignment).toHaveBeenCalledWith( command, @@ -88,32 +90,85 @@ describe('JobAssignmentController', () => { const command: JobAssignmentCommand = jobAssignmentCommandFixture; const result = await controller.assignJob(dto, { token: jobAssignmentToken, + user: { is_stake_eligible: true }, } as RequestWithUser); expect(result).toEqual( jobAssignmentServiceMock.processJobAssignment(command), ); }); + it('should throw ForbiddenException if user is not stake eligible in assignJob', async () => { + const dto: JobAssignmentDto = jobAssignmentDtoFixture; + await expect( + controller.assignJob(dto, { + token: jobAssignmentToken, + user: { is_stake_eligible: false }, + } as RequestWithUser), + ).rejects.toThrow(new ForbiddenException('Stake requirement not met')); + }); + it('should call service processGetAssignedJobs method with proper fields set', async () => { const dto: JobsFetchParamsDto = jobsFetchParamsDtoFixture; const command: JobsFetchParamsCommand = jobsFetchParamsCommandFixture; await controller.getAssignedJobs(dto, { token: jobAssignmentToken, + user: { is_stake_eligible: true }, } as RequestWithUser); expect(jobAssignmentService.processGetAssignedJobs).toHaveBeenCalledWith( command, ); }); + it('should return empty results if user is not stake eligible in getAssignedJobs', async () => { + const dto: JobsFetchParamsDto = jobsFetchParamsDtoFixture; + const result = await controller.getAssignedJobs(dto, { + token: jobAssignmentToken, + user: { is_stake_eligible: false }, + } as RequestWithUser); + expect(result).toEqual({ + page: 0, + page_size: 1, + total_pages: 1, + total_results: 0, + results: [], + }); + }); + it('should call service refreshAssigments method with proper fields set', async () => { const dto: RefreshJobDto = refreshJobDtoFixture; await controller.refreshAssigments(dto, { token: jobAssignmentToken, + user: { is_stake_eligible: true }, } as RequestWithUser); expect(jobAssignmentService.updateAssignmentsCache).toHaveBeenCalledWith({ oracleAddress: EXCHANGE_ORACLE_ADDRESS, token: TOKEN, }); }); + + it('should throw ForbiddenException if user is not stake eligible in refreshAssigments', async () => { + const dto: RefreshJobDto = refreshJobDtoFixture; + await expect( + controller.refreshAssigments(dto, { + token: jobAssignmentToken, + user: { is_stake_eligible: false }, + } as RequestWithUser), + ).rejects.toThrow(new ForbiddenException('Stake requirement not met')); + }); + }); + + describe('resignAssigment', () => { + it('should throw ForbiddenException if user is not stake eligible in resignAssigment', async () => { + const dto = { assignment_id: '1' }; + await expect( + controller.resignAssigment( + dto as any, + { + token: jobAssignmentToken, + user: { is_stake_eligible: false }, + } as RequestWithUser, + ), + ).rejects.toThrow(new ForbiddenException('Stake requirement not met')); + }); }); }); diff --git a/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts b/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts index be89ef3407..85fe4c11f4 100644 --- a/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts +++ b/packages/apps/human-app/server/src/modules/jobs-discovery/jobs-discovery.controller.ts @@ -51,6 +51,18 @@ export class JobsDiscoveryController { HttpStatus.FORBIDDEN, ); } + + // Require stake eligibility + if (!req.user?.is_stake_eligible) { + return { + page: 0, + page_size: 1, + total_pages: 1, + total_results: 0, + results: [], + }; + } + // TODO: temporal - THIRSTYFI if ( jobsDiscoveryParamsDto.oracle_address === diff --git a/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts b/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts index fb4e14b4bf..9b73a31176 100644 --- a/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/jobs-discovery/spec/jobs-discovery.controller.spec.ts @@ -14,6 +14,7 @@ import { dtoFixture, jobsDiscoveryParamsCommandFixture, responseFixture, + jobDiscoveryToken, } from './jobs-discovery.fixtures'; import { jobsDiscoveryServiceMock } from './jobs-discovery.service.mock'; @@ -73,7 +74,7 @@ describe('JobsDiscoveryController', () => { const dto = dtoFixture; const command = jobsDiscoveryParamsCommandFixture; await controller.getJobs(dto, { - user: { qualifications: [] }, + user: { qualifications: [], is_stake_eligible: true }, token: command.token, } as any); command.data.qualifications = []; @@ -90,6 +91,22 @@ describe('JobsDiscoveryController', () => { ).rejects.toThrow( new HttpException('Jobs discovery is disabled', HttpStatus.FORBIDDEN), ); + (configServiceMock as any).jobsDiscoveryFlag = true; + }); + + it('should return empty results if user is not stake eligible', async () => { + const dto = dtoFixture; + const result = await controller.getJobs(dto, { + user: { qualifications: [], is_stake_eligible: false }, + token: jobDiscoveryToken, + } as any); + expect(result).toEqual({ + page: 0, + page_size: 1, + total_pages: 1, + total_results: 0, + results: [], + }); }); }); }); diff --git a/packages/apps/human-app/server/src/modules/staking/model/staking.model.ts b/packages/apps/human-app/server/src/modules/staking/model/staking.model.ts new file mode 100644 index 0000000000..a6b6f9d95b --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/model/staking.model.ts @@ -0,0 +1,20 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; + +export class StakeSummaryResponse { + @ApiProperty() + exchange_stake: number; + + @ApiProperty({ name: 'on_chain_stake' }) + on_chain_stake: number; + + @ApiPropertyOptional() + exchange_error?: string | null; + + @ApiPropertyOptional() + on_chain_error?: string | null; +} + +export class StakeConfigResponse { + min_threshold: number; + eligibility_enabled: boolean; +} diff --git a/packages/apps/human-app/server/src/modules/staking/spec/staking.controller.spec.ts b/packages/apps/human-app/server/src/modules/staking/spec/staking.controller.spec.ts new file mode 100644 index 0000000000..f92224d522 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/spec/staking.controller.spec.ts @@ -0,0 +1,50 @@ +import { classes } from '@automapper/classes'; +import { AutomapperModule } from '@automapper/nestjs'; +import { Test, TestingModule } from '@nestjs/testing'; +import { RequestWithUser } from '../../../common/interfaces/jwt'; +import { TOKEN } from './staking.fixtures'; +import { StakingService } from '../staking.service'; +import { StakingController } from '../staking.controller'; +import { stakingServiceMock } from './staking.service.mock'; + +describe('StakingController', () => { + let controller: StakingController; + let service: StakingService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [StakingController], + imports: [ + AutomapperModule.forRoot({ + strategyInitializer: classes(), + }), + ], + providers: [ + StakingService, + { + provide: StakingService, + useValue: stakingServiceMock, + }, + ], + }) + .overrideProvider(StakingService) + .useValue(stakingServiceMock) + .compile(); + + controller = module.get(StakingController); + service = module.get(StakingService); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); + + describe('getStakeSummary', () => { + it('should call service.getStakeSummary with token and return response', async () => { + const req: RequestWithUser = { token: TOKEN } as RequestWithUser; + const result = await controller.getStakeSummary(req); + expect(service.getStakeSummary).toHaveBeenCalledWith(TOKEN); + expect(result).toEqual(stakingServiceMock.getStakeSummary(TOKEN)); + }); + }); +}); diff --git a/packages/apps/human-app/server/src/modules/staking/spec/staking.fixtures.ts b/packages/apps/human-app/server/src/modules/staking/spec/staking.fixtures.ts new file mode 100644 index 0000000000..93699eef96 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/spec/staking.fixtures.ts @@ -0,0 +1,11 @@ +export const TOKEN = 'test_user_token'; + +export const stakeSummaryResponseFixture = { + exchange_stake: '1000', + on_chain_stake: '500', +}; + +export const stakeConfigResponseFixture = { + min_threshold: '1000', + eligibility_enabled: true, +}; diff --git a/packages/apps/human-app/server/src/modules/staking/spec/staking.service.mock.ts b/packages/apps/human-app/server/src/modules/staking/spec/staking.service.mock.ts new file mode 100644 index 0000000000..582f931236 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/spec/staking.service.mock.ts @@ -0,0 +1,9 @@ +import { + stakeConfigResponseFixture, + stakeSummaryResponseFixture, +} from './staking.fixtures'; + +export const stakingServiceMock = { + getStakeSummary: jest.fn().mockReturnValue(stakeSummaryResponseFixture), + getStakeConfig: jest.fn().mockReturnValue(stakeConfigResponseFixture), +}; diff --git a/packages/apps/human-app/server/src/modules/staking/spec/staking.service.spec.ts b/packages/apps/human-app/server/src/modules/staking/spec/staking.service.spec.ts new file mode 100644 index 0000000000..ad97851205 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/spec/staking.service.spec.ts @@ -0,0 +1,55 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ReputationOracleGateway } from '../../../integrations/reputation-oracle/reputation-oracle.gateway'; +import { StakingService } from '../staking.service'; +import { + stakeConfigResponseFixture, + stakeSummaryResponseFixture, + TOKEN, +} from './staking.fixtures'; + +describe('StakingService', () => { + let service: StakingService; + let reputationOracleMock: Partial; + + beforeEach(async () => { + reputationOracleMock = { + getStakeSummary: jest.fn(), + getStakeConfig: jest.fn(), + }; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + StakingService, + { provide: ReputationOracleGateway, useValue: reputationOracleMock }, + ], + }).compile(); + + service = module.get(StakingService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('getStakeSummary', () => { + it('should retrieve stake summary', async () => { + (reputationOracleMock.getStakeSummary as jest.Mock).mockResolvedValue( + stakeSummaryResponseFixture, + ); + const result = await service.getStakeSummary(TOKEN); + expect(reputationOracleMock.getStakeSummary).toHaveBeenCalledWith(TOKEN); + expect(result).toEqual(stakeSummaryResponseFixture); + }); + }); + + describe('getStakeConfig', () => { + it('should retrieve stake config', async () => { + (reputationOracleMock.getStakeConfig as jest.Mock).mockResolvedValue( + stakeConfigResponseFixture, + ); + const result = await service.getStakeConfig(); + expect(reputationOracleMock.getStakeConfig).toHaveBeenCalledWith(); + expect(result).toEqual(stakeConfigResponseFixture); + }); + }); +}); diff --git a/packages/apps/human-app/server/src/modules/staking/staking.controller.ts b/packages/apps/human-app/server/src/modules/staking/staking.controller.ts new file mode 100644 index 0000000000..f8bcdae90f --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/staking.controller.ts @@ -0,0 +1,25 @@ +import { Mapper } from '@automapper/core'; +import { InjectMapper } from '@automapper/nestjs'; +import { Controller, Get, Request } from '@nestjs/common'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { RequestWithUser } from '../../common/interfaces/jwt'; +import { StakingService } from './staking.service'; +import { StakeSummaryResponse } from './model/staking.model'; + +@ApiTags('Staking') +@ApiBearerAuth() +@Controller('/staking') +export class StakingController { + constructor( + private readonly service: StakingService, + @InjectMapper() private readonly mapper: Mapper, + ) {} + + @ApiOperation({ summary: 'Get exchange API keys stake summary' }) + @Get('/summary') + async getStakeSummary( + @Request() req: RequestWithUser, + ): Promise { + return this.service.getStakeSummary(req.token); + } +} diff --git a/packages/apps/human-app/server/src/modules/staking/staking.module.ts b/packages/apps/human-app/server/src/modules/staking/staking.module.ts new file mode 100644 index 0000000000..49bc184eda --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/staking.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { StakingController } from './staking.controller'; +import { StakingService } from './staking.service'; +import { ReputationOracleModule } from '../../integrations/reputation-oracle/reputation-oracle.module'; + +@Module({ + imports: [ReputationOracleModule], + controllers: [StakingController], + providers: [StakingService], + exports: [StakingService], +}) +export class StakingModule {} diff --git a/packages/apps/human-app/server/src/modules/staking/staking.service.ts b/packages/apps/human-app/server/src/modules/staking/staking.service.ts new file mode 100644 index 0000000000..820c8f9361 --- /dev/null +++ b/packages/apps/human-app/server/src/modules/staking/staking.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@nestjs/common'; +import { ReputationOracleGateway } from '../../integrations/reputation-oracle/reputation-oracle.gateway'; +import { + StakeConfigResponse, + StakeSummaryResponse, +} from './model/staking.model'; + +@Injectable() +export class StakingService { + constructor(private readonly reputationOracle: ReputationOracleGateway) {} + + getStakeSummary(token: string): Promise { + return this.reputationOracle.getStakeSummary(token); + } + + getStakeConfig(): Promise { + return this.reputationOracle.getStakeConfig(); + } +} diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts index 95e4889355..c8df57939b 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.spec.ts @@ -1,15 +1,22 @@ +import { ChainId } from '@human-protocol/sdk'; import { ConfigModule } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; -import { UiConfigurationController } from './ui-configuration.controller'; + import { EnvironmentConfigService } from '../../common/config/environment-config.service'; -import { ChainId } from '@human-protocol/sdk'; +import { StakingService } from '../staking/staking.service'; +import { UiConfigurationController } from './ui-configuration.controller'; process.env.CHAIN_IDS_ENABLED = '80002,11155111'; describe('UiConfigurationController', () => { let controller: UiConfigurationController; + let stakingServiceMock: Pick, 'getStakeConfig'>; beforeAll(async () => { + stakingServiceMock = { + getStakeConfig: jest.fn(), + }; + const module: TestingModule = await Test.createTestingModule({ imports: [ ConfigModule.forRoot({ @@ -17,7 +24,13 @@ describe('UiConfigurationController', () => { isGlobal: true, }), ], - providers: [EnvironmentConfigService], + providers: [ + EnvironmentConfigService, + { + provide: StakingService, + useValue: stakingServiceMock, + }, + ], controllers: [UiConfigurationController], }).compile(); @@ -27,10 +40,16 @@ describe('UiConfigurationController', () => { }); it('should return proper config', async () => { + stakingServiceMock.getStakeConfig.mockResolvedValueOnce({ + eligibility_enabled: true, + min_threshold: Math.random(), + }); + const result = await controller.getConfig(); expect(result.chainIdsEnabled).toEqual([ ChainId.POLYGON_AMOY, ChainId.SEPOLIA, ]); + expect(result.stakingEligibilityEnabled).toBe(true); }); }); diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts index 0ed982fe27..0c4107eb01 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.controller.ts @@ -3,6 +3,7 @@ import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; import { EnvironmentConfigService } from '../../common/config/environment-config.service'; import { Public } from '../../common/decorators'; import { UiConfigResponseDto } from './ui-configuration.dto'; +import { StakingService } from '../staking/staking.service'; @Controller() @Public() @@ -10,6 +11,7 @@ import { UiConfigResponseDto } from './ui-configuration.dto'; export class UiConfigurationController { constructor( private readonly environmentConfigService: EnvironmentConfigService, + private readonly stakingService: StakingService, ) {} @ApiOperation({ summary: 'Retrieve UI configuration' }) @@ -17,11 +19,15 @@ export class UiConfigurationController { type: UiConfigResponseDto, description: 'UI Configuration object', }) - @Header('Cache-Control', 'public, max-age=3600') + @Header('Cache-Control', 'public, max-age=600') @Get('/ui-config') public async getConfig(): Promise { + const stakingRequirementConfig = await this.stakingService.getStakeConfig(); + return { chainIdsEnabled: this.environmentConfigService.chainIdsEnabled, + stakingEligibilityEnabled: stakingRequirementConfig.eligibility_enabled, + minThreshold: stakingRequirementConfig.min_threshold, }; } } diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts index 864757461b..6633c8cf49 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.dto.ts @@ -9,4 +9,15 @@ export class UiConfigResponseDto { enumName: 'ChainId', }) chainIdsEnabled: ChainId[]; + + @ApiProperty({ + description: + 'Indicated if stake eligibility check enabled on app & oracles', + }) + stakingEligibilityEnabled: boolean; + + @ApiProperty({ + description: 'Minimum staking threshold required for eligibility', + }) + minThreshold: number; } diff --git a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts index d14d2d39bd..2e99816674 100644 --- a/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts +++ b/packages/apps/human-app/server/src/modules/ui-configuration/ui-configuration.module.ts @@ -1,7 +1,9 @@ import { Module } from '@nestjs/common'; import { UiConfigurationController } from './ui-configuration.controller'; +import { StakingModule } from '../staking/staking.module'; @Module({ + imports: [StakingModule], controllers: [UiConfigurationController], }) export class UiConfigurationModule {} diff --git a/packages/apps/reputation-oracle/server/.env.example b/packages/apps/reputation-oracle/server/.env.example index c3c6a028ce..80da4aa283 100644 --- a/packages/apps/reputation-oracle/server/.env.example +++ b/packages/apps/reputation-oracle/server/.env.example @@ -97,3 +97,6 @@ NDA_URL=https://humanprotocol.org # HUMAN App secret key for auth in RepO HUMAN_APP_SECRET_KEY=sk_example_1VwUpBMO8H0v4Pmu4TPiWFEwuMguW4PkozSban4Rfbc + +# Aes +AES_ENCRYPTION_KEY=e59a0bb854ff5b338fbfc86452690be2 diff --git a/packages/apps/reputation-oracle/server/src/app.module.ts b/packages/apps/reputation-oracle/server/src/app.module.ts index a064f1b5c9..a57b33c078 100644 --- a/packages/apps/reputation-oracle/server/src/app.module.ts +++ b/packages/apps/reputation-oracle/server/src/app.module.ts @@ -14,11 +14,13 @@ import { AbuseModule } from './modules/abuse'; import { AuthModule } from './modules/auth'; import { CronJobModule } from './modules/cron-job'; import { EscrowCompletionModule } from './modules/escrow-completion'; +import { ExchangeApiKeysModule } from './modules/exchange-api-keys'; import { HealthModule } from './modules/health'; import { KycModule } from './modules/kyc'; import { NDAModule } from './modules/nda'; import { QualificationModule } from './modules/qualification'; import { ReputationModule } from './modules/reputation'; +import { StakingModule } from './modules/staking'; import { UserModule } from './modules/user'; import { IncomingWebhookModule, @@ -72,6 +74,8 @@ import Environment from './utils/environment'; CronJobModule, UserModule, NDAModule, + ExchangeApiKeysModule, + StakingModule, EscrowCompletionModule, HealthModule, KycModule, diff --git a/packages/apps/reputation-oracle/server/src/common/constants/index.ts b/packages/apps/reputation-oracle/server/src/common/constants/index.ts index 1bacfb11fd..02d82593be 100644 --- a/packages/apps/reputation-oracle/server/src/common/constants/index.ts +++ b/packages/apps/reputation-oracle/server/src/common/constants/index.ts @@ -12,3 +12,20 @@ export const RESEND_EMAIL_VERIFICATION_PATH = export const LOGOUT_PATH = '/auth/logout'; export const BACKOFF_INTERVAL_SECONDS = 120; + +export enum SupportedExchange { + MEXC = 'mexc', + GATE = 'gate', +} + +export type SupportedExchangeInfo = { + name: SupportedExchange; + displayName: string; +}; + +export const SUPPORTED_EXCHANGES_INFO: readonly SupportedExchangeInfo[] = [ + { name: SupportedExchange.MEXC, displayName: 'MEXC' }, + { name: SupportedExchange.GATE, displayName: 'Gate' }, +] as const; + +export const DEFAULT_TIMEOUT_MS = 5000; diff --git a/packages/apps/reputation-oracle/server/src/common/interceptors/transform.interceptor.ts b/packages/apps/reputation-oracle/server/src/common/interceptors/transform.interceptor.ts index 5408ab7dd1..c82683d25e 100644 --- a/packages/apps/reputation-oracle/server/src/common/interceptors/transform.interceptor.ts +++ b/packages/apps/reputation-oracle/server/src/common/interceptors/transform.interceptor.ts @@ -23,6 +23,10 @@ export class TransformInterceptor implements NestInterceptor { request.query = this.transformRequestData(request.query); } + if (request.params) { + request.params = this.transformRequestData(request.params); + } + return next.handle().pipe(map((data) => this.transformResponseData(data))); } diff --git a/packages/apps/reputation-oracle/server/src/config/config.module.ts b/packages/apps/reputation-oracle/server/src/config/config.module.ts index eb3e0f4af0..1adb75e47f 100644 --- a/packages/apps/reputation-oracle/server/src/config/config.module.ts +++ b/packages/apps/reputation-oracle/server/src/config/config.module.ts @@ -4,6 +4,7 @@ import { ConfigModule } from '@nestjs/config'; import { AuthConfigService } from './auth-config.service'; import { DatabaseConfigService } from './database-config.service'; import { EmailConfigService } from './email-config.service'; +import { EncryptionConfigService } from './encryption-config.service'; import { HCaptchaConfigService } from './hcaptcha-config.service'; import { KycConfigService } from './kyc-config.service'; import { NDAConfigService } from './nda-config.service'; @@ -12,6 +13,7 @@ import { ReputationConfigService } from './reputation-config.service'; import { S3ConfigService } from './s3-config.service'; import { ServerConfigService } from './server-config.service'; import { SlackConfigService } from './slack-config.service'; +import { StakingConfigService } from './staking-config.service'; import { Web3ConfigService } from './web3-config.service'; @Global() @@ -21,11 +23,13 @@ import { Web3ConfigService } from './web3-config.service'; AuthConfigService, DatabaseConfigService, EmailConfigService, + EncryptionConfigService, HCaptchaConfigService, KycConfigService, NDAConfigService, PGPConfigService, ReputationConfigService, + StakingConfigService, S3ConfigService, ServerConfigService, SlackConfigService, @@ -35,11 +39,13 @@ import { Web3ConfigService } from './web3-config.service'; AuthConfigService, DatabaseConfigService, EmailConfigService, + EncryptionConfigService, HCaptchaConfigService, KycConfigService, NDAConfigService, PGPConfigService, ReputationConfigService, + StakingConfigService, S3ConfigService, ServerConfigService, SlackConfigService, diff --git a/packages/apps/reputation-oracle/server/src/config/encryption-config.service.ts b/packages/apps/reputation-oracle/server/src/config/encryption-config.service.ts new file mode 100644 index 0000000000..ff5e8feb7b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/config/encryption-config.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +@Injectable() +export class EncryptionConfigService { + constructor(private configService: ConfigService) {} + + /** + * 32-byte key for AES encrpytion + */ + get aesEncryptionKey(): string { + return this.configService.getOrThrow('AES_ENCRYPTION_KEY'); + } +} diff --git a/packages/apps/reputation-oracle/server/src/config/env-schema.ts b/packages/apps/reputation-oracle/server/src/config/env-schema.ts index 98dc73b932..78876e7ec8 100644 --- a/packages/apps/reputation-oracle/server/src/config/env-schema.ts +++ b/packages/apps/reputation-oracle/server/src/config/env-schema.ts @@ -81,10 +81,27 @@ export const envValidator = Joi.object({ KYC_BASE_URL: Joi.string().uri({ scheme: ['http', 'https'] }), // Human App HUMAN_APP_SECRET_KEY: Joi.string().required(), + // Staking configuration + STAKING_ASSET: Joi.string().description( + 'Asset symbol to check for staking (default HMT)', + ), + STAKING_MIN_THRESHOLD: Joi.number() + .min(0) + .description('Minimum asset amount to qualify as staked'), + STAKING_TIMEOUT_MS: Joi.number() + .integer() + .min(100) + .description('HTTP timeout for exchange staking checks in ms'), + STAKING_ELIGIBILITY_ENABLED: Joi.string() + .valid('true', 'false') + .default('false') + .description('Enable or disable staking eligibility checks'), // Slack notifications ABUSE_SLACK_WEBHOOK_URL: Joi.string() .uri({ scheme: ['http', 'https'] }) .required(), ABUSE_SLACK_OAUTH_TOKEN: Joi.string().required(), ABUSE_SLACK_SIGNING_SECRET: Joi.string().required(), + // Encryption + AES_ENCRYPTION_KEY: Joi.string().required().length(32), }); diff --git a/packages/apps/reputation-oracle/server/src/config/index.ts b/packages/apps/reputation-oracle/server/src/config/index.ts index 2e76538048..5d1318cd56 100644 --- a/packages/apps/reputation-oracle/server/src/config/index.ts +++ b/packages/apps/reputation-oracle/server/src/config/index.ts @@ -3,11 +3,13 @@ export * from './env-schema'; export { AuthConfigService } from './auth-config.service'; export { DatabaseConfigService } from './database-config.service'; export { EmailConfigService } from './email-config.service'; +export { EncryptionConfigService } from './encryption-config.service'; export { HCaptchaConfigService } from './hcaptcha-config.service'; export { KycConfigService } from './kyc-config.service'; export { NDAConfigService } from './nda-config.service'; export { PGPConfigService } from './pgp-config.service'; export { ReputationConfigService } from './reputation-config.service'; +export { StakingConfigService } from './staking-config.service'; export { S3ConfigService } from './s3-config.service'; export { ServerConfigService } from './server-config.service'; export { Web3ConfigService, Web3Network } from './web3-config.service'; diff --git a/packages/apps/reputation-oracle/server/src/config/staking-config.service.ts b/packages/apps/reputation-oracle/server/src/config/staking-config.service.ts new file mode 100644 index 0000000000..174d3ed5d1 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/config/staking-config.service.ts @@ -0,0 +1,43 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +@Injectable() +export class StakingConfigService { + constructor(private readonly configService: ConfigService) {} + + /** + * Default asset symbol to check for staking eligibility. + * Default: 'HMT' + */ + get asset(): string { + return this.configService.get('STAKING_ASSET', 'HMT'); + } + + /** + * Minimum threshold (asset units) required for staking eligibility. + * Default: 1000 + */ + get minThreshold(): number { + return Number(this.configService.get('STAKING_MIN_THRESHOLD')) || 1000; + } + + /** + * Optional per-exchange HTTP timeout, in milliseconds. + * Default: 2000 + */ + get timeoutMs(): number { + return Number(this.configService.get('STAKING_TIMEOUT_MS')) || 2000; + } + + /** + * Feature flag to enable/disable staking eligibility enforcement. + * When disabled, eligibility will be treated as true unconditionally. + * Default: false + */ + get eligibilityEnabled(): boolean { + return ( + this.configService.get('STAKING_ELIGIBILITY_ENABLED', 'false') === + 'true' + ); + } +} diff --git a/packages/apps/reputation-oracle/server/src/database/database.module.ts b/packages/apps/reputation-oracle/server/src/database/database.module.ts index 093c5d7abf..c8bb6dc8f3 100644 --- a/packages/apps/reputation-oracle/server/src/database/database.module.ts +++ b/packages/apps/reputation-oracle/server/src/database/database.module.ts @@ -13,6 +13,7 @@ import { TokenEntity } from '@/modules/auth/token.entity'; import { CronJobEntity } from '@/modules/cron-job/cron-job.entity'; import { EscrowCompletionEntity } from '@/modules/escrow-completion/escrow-completion.entity'; import { EscrowPayoutsBatchEntity } from '@/modules/escrow-completion/escrow-payouts-batch.entity'; +import { ExchangeApiKeyEntity } from '@/modules/exchange-api-keys'; import { KycEntity } from '@/modules/kyc/kyc.entity'; import { QualificationEntity } from '@/modules/qualification/qualification.entity'; import { UserQualificationEntity } from '@/modules/qualification/user-qualification.entity'; @@ -71,6 +72,7 @@ import { TypeOrmLoggerModule, TypeOrmLoggerService } from './typeorm'; OutgoingWebhookEntity, EscrowCompletionEntity, EscrowPayoutsBatchEntity, + ExchangeApiKeyEntity, ReputationEntity, TokenEntity, UserEntity, diff --git a/packages/apps/reputation-oracle/server/src/database/migrations/1761653939799-exchangeApiKeys.ts b/packages/apps/reputation-oracle/server/src/database/migrations/1761653939799-exchangeApiKeys.ts new file mode 100644 index 0000000000..3b5f7f91bd --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/database/migrations/1761653939799-exchangeApiKeys.ts @@ -0,0 +1,27 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class ExchangeApiKeys1761653939799 implements MigrationInterface { + name = 'ExchangeApiKeys1761653939799'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "hmt"."exchange_api_keys" ("id" SERIAL NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL, "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL, "exchange_name" character varying(20) NOT NULL, "api_key" character varying(1000) NOT NULL, "secret_key" character varying(10000) NOT NULL, "user_id" integer NOT NULL, CONSTRAINT "PK_3751a8a0ef5354b32b06ea43983" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE UNIQUE INDEX "IDX_96ee74195b058a1b55afc49f67" ON "hmt"."exchange_api_keys" ("user_id") `, + ); + await queryRunner.query( + `ALTER TABLE "hmt"."exchange_api_keys" ADD CONSTRAINT "FK_96ee74195b058a1b55afc49f673" FOREIGN KEY ("user_id") REFERENCES "hmt"."users"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "hmt"."exchange_api_keys" DROP CONSTRAINT "FK_96ee74195b058a1b55afc49f673"`, + ); + await queryRunner.query( + `DROP INDEX "hmt"."IDX_96ee74195b058a1b55afc49f67"`, + ); + await queryRunner.query(`DROP TABLE "hmt"."exchange_api_keys"`); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/auth/auth.module.ts b/packages/apps/reputation-oracle/server/src/modules/auth/auth.module.ts index f613211882..bcb7cd27c6 100644 --- a/packages/apps/reputation-oracle/server/src/modules/auth/auth.module.ts +++ b/packages/apps/reputation-oracle/server/src/modules/auth/auth.module.ts @@ -4,8 +4,10 @@ import { JwtModule } from '@nestjs/jwt'; import { AuthConfigService } from '@/config'; import { HCaptchaModule } from '@/integrations/hcaptcha'; import { EmailModule } from '@/modules/email'; +import { ExchangeModule } from '@/modules/exchange'; +import { ExchangeApiKeysModule } from '@/modules/exchange-api-keys'; +import { StakingModule } from '@/modules/staking'; import { UserModule } from '@/modules/user'; -import { Web3Module } from '@/modules/web3'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; @@ -25,8 +27,10 @@ import { TokenRepository } from './token.repository'; }, }), }), - Web3Module, HCaptchaModule, + ExchangeModule, + ExchangeApiKeysModule, + StakingModule, EmailModule, ], providers: [JwtHttpStrategy, AuthService, TokenRepository], diff --git a/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.spec.ts index 121e37346d..9606f53499 100644 --- a/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.spec.ts @@ -11,10 +11,12 @@ import { SignatureType, UserStatus, UserRole } from '@/common/enums'; import { AuthConfigService, NDAConfigService, + StakingConfigService, ServerConfigService, Web3ConfigService, } from '@/config'; import { EmailAction, EmailService } from '@/modules/email'; +import { StakingService } from '@/modules/staking'; import { SiteKeyRepository } from '@/modules/user'; import { UserEntity, UserRepository, UserService } from '@/modules/user'; import { generateOperator, generateWorkerUser } from '@/modules/user/fixtures'; @@ -41,6 +43,12 @@ const mockAuthConfigService: Omit = { forgotPasswordExpiresIn: 86400000, humanAppSecretKey: faker.string.alphanumeric({ length: 42 }), }; +const mockStakingConfigService: Omit = { + eligibilityEnabled: true, + minThreshold: 100, + asset: 'ETH', + timeoutMs: 2000, +}; const mockEmailService = createMock(); @@ -56,6 +64,7 @@ const mockSiteKeyRepository = createMock(); const mockTokenRepository = createMock(); const mockUserRepository = createMock(); const mockUserService = createMock(); +const mockStakingService = createMock(); describe('AuthService', () => { let service: AuthService; @@ -85,6 +94,8 @@ describe('AuthService', () => { { provide: UserRepository, useValue: mockUserRepository }, { provide: UserService, useValue: mockUserService }, { provide: Web3ConfigService, useValue: mockWeb3ConfigService }, + { provide: StakingService, useValue: mockStakingService }, + { provide: StakingConfigService, useValue: mockStakingConfigService }, ], }).compile(); @@ -626,6 +637,7 @@ describe('AuthService', () => { wallet_address: user.evmAddress, role: user.role, kyc_status: user.kyc?.status, + is_stake_eligible: true, nda_signed: user.ndaSignedUrl === mockNdaConfigService.latestNdaUrl, reputation_network: mockWeb3ConfigService.operatorAddress, qualifications: user.userQualifications @@ -635,6 +647,11 @@ describe('AuthService', () => { : [], }; + const spyOncheckStakeEligible = jest + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .spyOn(service as any, 'checkStakeEligible') + .mockImplementation(); + spyOncheckStakeEligible.mockResolvedValueOnce(true); const spyOnGenerateTokens = jest .spyOn(service, 'generateTokens') .mockImplementation(); @@ -651,10 +668,132 @@ describe('AuthService', () => { expectedJwtPayload, ); + expect(spyOncheckStakeEligible).toHaveBeenCalledTimes(1); + + spyOncheckStakeEligible.mockRestore(); spyOnGenerateTokens.mockRestore(); }); }); + describe('checkStakeEligible', () => { + it('returns true when feature flag disabled', async () => { + const user = generateWorkerUser(); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).eligibilityEnabled = false; + + const result = await service['checkStakeEligible'](user); + + expect(result).toBe(true); + expect( + mockStakingService.getExchangeStakedBalance, + ).not.toHaveBeenCalled(); + expect(mockStakingService.getOnChainStakedBalance).not.toHaveBeenCalled(); + }); + + it('returns true when exchange balance meets threshold (no on-chain call)', async () => { + const user = generateWorkerUser(); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).eligibilityEnabled = true; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).minThreshold = 1000; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).asset = 'HMT'; + + mockStakingService.getExchangeStakedBalance.mockResolvedValueOnce(1500); + + const result = await service['checkStakeEligible'](user); + + expect(result).toBe(true); + expect(mockStakingService.getExchangeStakedBalance).toHaveBeenCalledWith( + user.id, + ); + expect(mockStakingService.getOnChainStakedBalance).not.toHaveBeenCalled(); + }); + + it('returns true when exchange balance below threshold but on-chain makes up the difference', async () => { + const user = generateWorkerUser({ + privateKey: generateEthWallet().privateKey, + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).eligibilityEnabled = true; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).minThreshold = 1000; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).asset = 'HMT'; + + mockStakingService.getExchangeStakedBalance.mockResolvedValueOnce(400); + mockStakingService.getOnChainStakedBalance.mockResolvedValueOnce(600); + + const result = await service['checkStakeEligible'](user); + + expect(result).toBe(true); + expect(mockStakingService.getExchangeStakedBalance).toHaveBeenCalledWith( + user.id, + ); + expect(mockStakingService.getOnChainStakedBalance).toHaveBeenCalledTimes( + 1, + ); + expect(mockStakingService.getOnChainStakedBalance).toHaveBeenCalledWith( + user.evmAddress, + ); + }); + + it('returns false when no exchange keys and on-chain stake below threshold', async () => { + const user = generateWorkerUser({ + privateKey: generateEthWallet().privateKey, + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).eligibilityEnabled = true; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).minThreshold = 1000; + + mockStakingService.getExchangeStakedBalance.mockResolvedValueOnce(0); + mockStakingService.getOnChainStakedBalance.mockResolvedValueOnce(500); + + const result = await service['checkStakeEligible'](user); + + expect(result).toBe(false); + expect(mockStakingService.getExchangeStakedBalance).toHaveBeenCalledWith( + user.id, + ); + expect(mockStakingService.getOnChainStakedBalance).toHaveBeenCalledTimes( + 1, + ); + }); + + it('continues on exchange error and returns based on on-chain stake', async () => { + const user = generateWorkerUser({ + privateKey: generateEthWallet().privateKey, + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).eligibilityEnabled = true; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).minThreshold = 1000; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (mockStakingConfigService as any).asset = 'HMT'; + + mockStakingService.getExchangeStakedBalance.mockRejectedValueOnce( + new Error('network'), + ); + mockStakingService.getOnChainStakedBalance.mockResolvedValueOnce(1200); + + const result = await service['checkStakeEligible'](user); + + expect(result).toBe(true); + expect(mockStakingService.getExchangeStakedBalance).toHaveBeenCalledWith( + user.id, + ); + expect(mockStakingService.getOnChainStakedBalance).toHaveBeenCalledTimes( + 1, + ); + }); + }); + describe('web3Auth', () => { it('should generate jwt payload for operator', async () => { const operator = generateOperator(); diff --git a/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts b/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts index b116b089ae..24afae39c2 100644 --- a/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts @@ -7,10 +7,12 @@ import { AuthConfigService, NDAConfigService, ServerConfigService, + StakingConfigService, Web3ConfigService, } from '@/config'; import logger from '@/logger'; import { EmailAction, EmailService } from '@/modules/email'; +import { StakingService } from '@/modules/staking'; import { OperatorStatus, SiteKeyRepository, @@ -56,6 +58,8 @@ export class AuthService { private readonly userRepository: UserRepository, private readonly userService: UserService, private readonly web3ConfigService: Web3ConfigService, + private readonly stakingService: StakingService, + private readonly stakingConfigService: StakingConfigService, ) {} async signup(email: string, password: string): Promise { @@ -244,6 +248,8 @@ export class AuthService { hCaptchaSiteKey = hCaptchaSiteKeys[0].siteKey; } + const stakeEligible = await this.checkStakeEligible(userEntity); + const jwtPayload = { email: userEntity.email, status: userEntity.status, @@ -253,6 +259,7 @@ export class AuthService { kyc_status: userEntity.kyc?.status, nda_signed: userEntity.ndaSignedUrl === this.ndaConfigService.latestNdaUrl, + is_stake_eligible: stakeEligible, reputation_network: this.web3ConfigService.operatorAddress, qualifications: userEntity.userQualifications ? userEntity.userQualifications.map( @@ -265,6 +272,44 @@ export class AuthService { return this.generateTokens(userEntity.id, jwtPayload); } + private async checkStakeEligible( + userEntity: Web2UserEntity | UserEntity, + ): Promise { + if (!this.stakingConfigService.eligibilityEnabled) return true; + + let inspectedStakeAmount = 0; + + try { + const exchangeBalance = + await this.stakingService.getExchangeStakedBalance(userEntity.id); + inspectedStakeAmount += exchangeBalance; + } catch (err) { + this.logger.warn('Failed to query exchange balance; continuing', { + userId: userEntity.id, + error: err, + }); + } + + if ( + inspectedStakeAmount < this.stakingConfigService.minThreshold && + userEntity.evmAddress + ) { + try { + const onChainStake = await this.stakingService.getOnChainStakedBalance( + userEntity.evmAddress, + ); + inspectedStakeAmount += onChainStake; + } catch (err) { + this.logger.warn('Failed to query on-chain stake; continuing', { + userId: userEntity.id, + error: err, + }); + } + } + + return inspectedStakeAmount >= this.stakingConfigService.minThreshold; + } + async web3Auth(userEntity: OperatorUserEntity): Promise { /** * NOTE diff --git a/packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.spec.ts new file mode 100644 index 0000000000..e9f856a784 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.spec.ts @@ -0,0 +1,85 @@ +import { faker } from '@faker-js/faker'; +import { Test } from '@nestjs/testing'; + +import { EncryptionConfigService } from '@/config'; + +import { AesEncryptionService } from './aes-encryption.service'; +import { generateAesEncryptionKey } from './fixtures'; + +const HEX_FORMAT_REGEX = /[0-9a-f]+/; + +const mockGetAesEncryptionKey = jest.fn(); + +const mockEncryptionConfigService: Omit< + EncryptionConfigService, + 'configService' +> = { + get aesEncryptionKey() { + return mockGetAesEncryptionKey(); + }, +}; + +describe('AesEncryptionService', () => { + let aesEncryptionService: AesEncryptionService; + + beforeAll(async () => { + const moduleRef = await Test.createTestingModule({ + providers: [ + { + provide: EncryptionConfigService, + useValue: mockEncryptionConfigService, + }, + AesEncryptionService, + ], + }).compile(); + + aesEncryptionService = + moduleRef.get(AesEncryptionService); + }); + + beforeEach(() => { + mockGetAesEncryptionKey.mockReturnValue(generateAesEncryptionKey()); + }); + + it('should be defined', () => { + expect(aesEncryptionService).toBeDefined(); + }); + + it('should encrypt data and return envelope string', async () => { + const data = faker.lorem.lines(); + + const envelope = await aesEncryptionService.encrypt(Buffer.from(data)); + + expect(typeof envelope).toBe('string'); + + const [authTag, encrypted, iv] = envelope.split(':'); + + expect(authTag).toMatch(HEX_FORMAT_REGEX); + expect(authTag).toHaveLength(24); + + expect(encrypted).toMatch(HEX_FORMAT_REGEX); + + expect(iv).toHaveLength(32); + expect(iv).toMatch(HEX_FORMAT_REGEX); + }); + + it('should decrypt data encrypted by itslef', async () => { + const data = faker.lorem.lines(); + + const encrypted = await aesEncryptionService.encrypt(Buffer.from(data)); + const decrypted = await aesEncryptionService.decrypt(encrypted); + + expect(decrypted.toString()).toBe(data); + }); + + it('should fail to decrypt if different encryption key used', async () => { + mockGetAesEncryptionKey.mockReturnValueOnce(generateAesEncryptionKey()); + mockGetAesEncryptionKey.mockReturnValueOnce(generateAesEncryptionKey()); + + const data = faker.lorem.lines(); + + const encrypted = await aesEncryptionService.encrypt(Buffer.from(data)); + + await expect(aesEncryptionService.decrypt(encrypted)).rejects.toThrow(); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.ts b/packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.ts new file mode 100644 index 0000000000..d42ddbfa30 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/encryption/aes-encryption.service.ts @@ -0,0 +1,100 @@ +import crypto from 'crypto'; + +import { Injectable } from '@nestjs/common'; + +import { EncryptionConfigService } from '@/config'; +import logger from '@/logger'; + +const ALGORITHM = 'aes-256-gcm'; +const GCM_IV_LENGTH_BYTES = 12; + +/** + * Security note: + * - Best practice is to use one encryption key per purpose (e.g., exchange API keys, PII, etc.). + * - At the moment, we only encrypt exchange API keys and therefore use a single key + * provided by EncryptionConfigService.aesEncryptionKey. + * - If/when we start encrypting different kinds of data, we should switch to per-purpose keys: + * - add dedicated config entries for each purpose (e.g., ENCRYPTION_USER_EXCHANGE_API_KEY, ...), + * - update this service so encrypt/decrypt accept an explicit encryptionKey parameter, + * - and ensure callers pass the correct key for the data they are encrypting/decrypting. + */ + +type EncryptionOutput = { + encrypted: Buffer; + iv: Buffer; + authTag: Buffer; +}; + +@Injectable() +export class AesEncryptionService { + private readonly logger = logger.child({ + context: AesEncryptionService.name, + }); + + constructor( + private readonly encryptionConfigService: EncryptionConfigService, + ) {} + + private composeEnvelopeString({ + encrypted, + authTag, + iv, + }: EncryptionOutput): string { + return `${iv.toString('hex')}:${encrypted.toString('hex')}:${authTag.toString('hex')}`; + } + + private parseEnvelopeString(envelope: string): EncryptionOutput { + const [iv, encrypted, authTag] = envelope.split(':'); + + if (!iv || !encrypted || !authTag) { + throw new Error('Invalid AES envelope'); + } + + return { + iv: Buffer.from(iv, 'hex'), + encrypted: Buffer.from(encrypted, 'hex'), + authTag: Buffer.from(authTag, 'hex'), + }; + } + + async encrypt(data: Buffer): Promise { + const encryptionKey = this.encryptionConfigService.aesEncryptionKey; + + const iv = crypto.randomBytes(GCM_IV_LENGTH_BYTES); + + const cipher = crypto.createCipheriv( + ALGORITHM, + Buffer.from(encryptionKey), + iv, + ); + + const encrypted = Buffer.concat([cipher.update(data), cipher.final()]); + const authTag = cipher.getAuthTag(); + + return this.composeEnvelopeString({ + iv, + encrypted, + authTag, + }); + } + + async decrypt(envelope: string): Promise { + const { iv, encrypted, authTag } = this.parseEnvelopeString(envelope); + + const encryptionKey = this.encryptionConfigService.aesEncryptionKey; + + const decipher = crypto.createDecipheriv( + ALGORITHM, + Buffer.from(encryptionKey), + iv, + ); + decipher.setAuthTag(authTag); + + const decrypted = Buffer.concat([ + decipher.update(encrypted), + decipher.final(), + ]); + + return decrypted; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/encryption/encryption.module.ts b/packages/apps/reputation-oracle/server/src/modules/encryption/encryption.module.ts index 623c981886..6583f9d356 100644 --- a/packages/apps/reputation-oracle/server/src/modules/encryption/encryption.module.ts +++ b/packages/apps/reputation-oracle/server/src/modules/encryption/encryption.module.ts @@ -2,11 +2,12 @@ import { Module } from '@nestjs/common'; import { Web3Module } from '@/modules/web3'; +import { AesEncryptionService } from './aes-encryption.service'; import { PgpEncryptionService } from './pgp-encryption.service'; @Module({ imports: [Web3Module], - providers: [PgpEncryptionService], - exports: [PgpEncryptionService], + providers: [AesEncryptionService, PgpEncryptionService], + exports: [AesEncryptionService, PgpEncryptionService], }) export class EncryptionModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/encryption/fixtures/index.ts b/packages/apps/reputation-oracle/server/src/modules/encryption/fixtures/index.ts new file mode 100644 index 0000000000..656d5464ac --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/encryption/fixtures/index.ts @@ -0,0 +1,14 @@ +import { faker } from '@faker-js/faker'; + +export const mockEncryptionConfigService = { + // 32-byte key for AES-256-GCM tests + aesEncryptionKey: generateAesEncryptionKey(), +}; + +/** + * Generates random key for AES encryption + * with the key length .expected by the app + */ +export function generateAesEncryptionKey(): string { + return faker.string.sample(32); +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-key.entity.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-key.entity.ts new file mode 100644 index 0000000000..5a9252614e --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-key.entity.ts @@ -0,0 +1,24 @@ +import { Column, Entity, Index, ManyToOne } from 'typeorm'; + +import { DATABASE_SCHEMA_NAME } from '@/common/constants'; +import { BaseEntity } from '@/database'; +import type { UserEntity } from '@/modules/user'; + +@Entity({ schema: DATABASE_SCHEMA_NAME, name: 'exchange_api_keys' }) +@Index(['userId'], { unique: true }) +export class ExchangeApiKeyEntity extends BaseEntity { + @Column('varchar', { length: 20 }) + exchangeName: string; + + @Column('varchar', { length: 1000 }) + apiKey: string; + + @Column('varchar', { length: 10000 }) + secretKey: string; + + @ManyToOne('UserEntity', { persistence: false, onDelete: 'CASCADE' }) + user?: UserEntity; + + @Column() + userId: number; +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts new file mode 100644 index 0000000000..df34ad7f2c --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.controller.ts @@ -0,0 +1,136 @@ +import { + Body, + Controller, + Delete, + ForbiddenException, + Get, + HttpCode, + Param, + Post, + Req, + UseFilters, +} from '@nestjs/common'; +import { + ApiBearerAuth, + ApiBody, + ApiOperation, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; + +import type { RequestWithUser } from '@/common/types'; +import Environment from '@/utils/environment'; + +import { + EnrollExchangeApiKeysDto, + EnrollExchangeApiKeysResponseDto, + EnrolledApiKeyDto, + ExchangeNameParamDto, + SupportedExchangeDto, +} from './exchange-api-keys.dto'; +import { ExchangeApiKeysControllerErrorsFilter } from './exchange-api-keys.error-filter'; +import { ExchangeApiKeyNotFoundError } from './exchange-api-keys.errors'; +import { ExchangeApiKeysRepository } from './exchange-api-keys.repository'; +import { ExchangeApiKeysService } from './exchange-api-keys.service'; + +@ApiTags('Exchange API Keys') +@ApiBearerAuth() +@UseFilters(ExchangeApiKeysControllerErrorsFilter) +@Controller('exchange-api-keys') +export class ExchangeApiKeysController { + constructor( + private readonly exchangeApiKeysService: ExchangeApiKeysService, + private readonly exchangeApiKeysRepository: ExchangeApiKeysRepository, + ) {} + + @ApiOperation({ + summary: 'Retrieve enrolled exchange with api key', + description: 'Returns the enrolled api key for exchange w/o secret key', + }) + @ApiResponse({ + status: 200, + type: EnrolledApiKeyDto, + }) + @Get('/') + async retrieveEnrolledApiKeys( + @Req() request: RequestWithUser, + ): Promise { + const userId = request.user.id; + + const apiKey = await this.exchangeApiKeysService.retrieve(userId); + if (!apiKey) { + return null; + } + + return { + exchangeName: apiKey.exchangeName, + apiKey: apiKey.apiKey, + }; + } + + @ApiOperation({ + summary: 'Enroll API keys for exchange', + description: + 'Enrolls API keys for provided exchange. If keys already exist for exchange - updates them', + }) + @ApiResponse({ + status: 200, + description: 'Exchange API keys enrolled', + type: EnrollExchangeApiKeysResponseDto, + }) + @ApiBody({ type: EnrollExchangeApiKeysDto }) + @HttpCode(200) + @Post('/:exchange_name') + async enroll( + @Req() request: RequestWithUser, + @Param() params: ExchangeNameParamDto, + @Body() data: EnrollExchangeApiKeysDto, + ): Promise { + const key = await this.exchangeApiKeysService.enroll({ + userId: request.user.id, + exchangeName: params.exchangeName, + apiKey: data.apiKey, + secretKey: data.secretKey, + }); + + return { id: key.id }; + } + + @ApiOperation({ + summary: 'Delete API keys', + }) + @ApiResponse({ + status: 204, + description: 'Exchange API keys deleted', + }) + @HttpCode(204) + @Delete('/') + async delete(@Req() request: RequestWithUser): Promise { + await this.exchangeApiKeysRepository.deleteByUser(request.user.id); + } + + @ApiOperation({ + summary: 'Retreive API keys for exchange', + description: + 'This functionality is purely for dev solely and works only in non-production environments', + }) + @Get('/exchange') + async retrieve(@Req() request: RequestWithUser): Promise { + if (!Environment.isDevelopment()) { + throw new ForbiddenException(); + } + + const apiKey = await this.exchangeApiKeysService.retrieve(request.user.id); + if (!apiKey) { + throw new ExchangeApiKeyNotFoundError(request.user.id); + } + return apiKey; + } + + @ApiOperation({ summary: 'List supported exchanges' }) + @ApiResponse({ status: 200, type: SupportedExchangeDto, isArray: true }) + @Get('/supported') + async getSupportedExchanges(): Promise { + return this.exchangeApiKeysService.getSupportedExchanges(); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.dto.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.dto.ts new file mode 100644 index 0000000000..e9546e80d8 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.dto.ts @@ -0,0 +1,48 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsEnum, IsNotEmpty, IsString, MaxLength } from 'class-validator'; + +import { SupportedExchange } from '@/common/constants'; + +export class EnrollExchangeApiKeysDto { + @ApiProperty({ name: 'api_key' }) + @IsString() + @IsNotEmpty() + @MaxLength(200) + apiKey: string; + + @ApiProperty({ name: 'secret_key' }) + @IsString() + @IsNotEmpty() + @MaxLength(5000) + secretKey: string; +} + +export class ExchangeNameParamDto { + @ApiProperty({ + name: 'exchange_name', + enum: SupportedExchange, + }) + @IsEnum(SupportedExchange) + exchangeName: SupportedExchange; +} + +export class EnrollExchangeApiKeysResponseDto { + @ApiProperty() + id: number; +} + +export class EnrolledApiKeyDto { + @ApiProperty({ name: 'exchange_name' }) + exchangeName: string; + + @ApiProperty({ name: 'api_key' }) + apiKey: string; +} + +export class SupportedExchangeDto { + @ApiProperty({ name: 'name' }) + name: string; + + @ApiProperty({ name: 'display_name' }) + displayName: string; +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.error-filter.ts new file mode 100644 index 0000000000..d4d629d673 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.error-filter.ts @@ -0,0 +1,54 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpStatus, +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +import logger from '@/logger'; +import { UserNotFoundError } from '@/modules/user'; + +import { + ExchangeApiKeyNotFoundError, + IncompleteKeySuppliedError, + KeyAuthorizationError, +} from './exchange-api-keys.errors'; +import { ExchangeApiClientError } from '../exchange/errors'; + +@Catch( + UserNotFoundError, + IncompleteKeySuppliedError, + KeyAuthorizationError, + ExchangeApiKeyNotFoundError, +) +export class ExchangeApiKeysControllerErrorsFilter implements ExceptionFilter { + private readonly logger = logger.child({ + context: ExchangeApiKeysControllerErrorsFilter.name, + }); + + catch(exception: Error, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + let status = HttpStatus.INTERNAL_SERVER_ERROR; + + if ( + exception instanceof UserNotFoundError || + exception instanceof IncompleteKeySuppliedError || + exception instanceof KeyAuthorizationError + ) { + status = HttpStatus.UNPROCESSABLE_ENTITY; + } else if (exception instanceof ExchangeApiClientError) { + status = HttpStatus.SERVICE_UNAVAILABLE; + } else if (exception instanceof ExchangeApiKeyNotFoundError) { + status = HttpStatus.NOT_FOUND; + } + + return response.status(status).json({ + message: exception.message, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.errors.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.errors.ts new file mode 100644 index 0000000000..b16190ddd2 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.errors.ts @@ -0,0 +1,19 @@ +import { BaseError } from '@/common/errors/base'; + +export class ExchangeApiKeyNotFoundError extends BaseError { + constructor(readonly userId: number) { + super('Exchange API key not found'); + } +} + +export class IncompleteKeySuppliedError extends BaseError { + constructor(readonly exchangeName: string) { + super('Incomplete credentials supplied for exchange'); + } +} + +export class KeyAuthorizationError extends BaseError { + constructor(readonly exchangeName: string) { + super("Provided API key can't be authorized on exchange"); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts new file mode 100644 index 0000000000..5d7a416588 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; + +import { EncryptionModule } from '@/modules/encryption'; +import { ExchangeModule } from '@/modules/exchange/exchange.module'; +import { UserModule } from '@/modules/user'; + +import { ExchangeApiKeysController } from './exchange-api-keys.controller'; +import { ExchangeApiKeysRepository } from './exchange-api-keys.repository'; +import { ExchangeApiKeysService } from './exchange-api-keys.service'; + +@Module({ + imports: [ExchangeModule, EncryptionModule, UserModule], + providers: [ExchangeApiKeysRepository, ExchangeApiKeysService], + controllers: [ExchangeApiKeysController], + exports: [ExchangeApiKeysRepository, ExchangeApiKeysService], +}) +export class ExchangeApiKeysModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.repository.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.repository.ts new file mode 100644 index 0000000000..ea0d264915 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.repository.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@nestjs/common'; +import { DataSource } from 'typeorm'; + +import { BaseRepository } from '@/database'; + +import { ExchangeApiKeyEntity } from './exchange-api-key.entity'; + +@Injectable() +export class ExchangeApiKeysRepository extends BaseRepository { + constructor(dataSource: DataSource) { + super(ExchangeApiKeyEntity, dataSource); + } + + async findOneByUserId(userId: number): Promise { + if (!userId) { + throw new Error('Invalid arguments'); + } + return this.findOne({ + where: { userId }, + }); + } + + async deleteByUser(userId: number): Promise { + if (!userId) { + throw new Error('userId is required'); + } + + await this.delete({ userId }); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.spec.ts new file mode 100644 index 0000000000..7869bf4f60 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.spec.ts @@ -0,0 +1,217 @@ +import { createMock } from '@golevelup/ts-jest'; +import { Test, TestingModule } from '@nestjs/testing'; + +import { SUPPORTED_EXCHANGES_INFO } from '@/common/constants'; +import { EncryptionConfigService } from '@/config/encryption-config.service'; +import { AesEncryptionService } from '@/modules/encryption/aes-encryption.service'; +import { mockEncryptionConfigService } from '@/modules/encryption/fixtures'; +import { ExchangeClientFactory } from '@/modules/exchange/exchange-client.factory'; + +// eslint-disable-next-line import/order +import { ExchangeApiKeysService } from './exchange-api-keys.service'; +import { UserEntity, UserNotFoundError, UserRepository } from '@/modules/user'; + +import { ExchangeApiKeyEntity } from './exchange-api-key.entity'; +import { KeyAuthorizationError } from './exchange-api-keys.errors'; +import { ExchangeApiKeysRepository } from './exchange-api-keys.repository'; +import { + generateExchangeApiKey, + generateExchangeApiKeysData, +} from './fixtures'; +import { ExchangeClient } from '../exchange/types'; + +const mockUserRepository = createMock(); +const mockExchangeApiKeysRepository = createMock(); +const mockExchangeClient = createMock(); +const mockExchangeClientFactory = { + create: jest.fn().mockReturnValue(mockExchangeClient), +}; + +describe('ExchangeApiKeysService', () => { + let exchangeApiKeysService: ExchangeApiKeysService; + let aesEncryptionService: AesEncryptionService; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ExchangeApiKeysService, + AesEncryptionService, + { provide: UserRepository, useValue: mockUserRepository }, + { + provide: ExchangeApiKeysRepository, + useValue: mockExchangeApiKeysRepository, + }, + { + provide: EncryptionConfigService, + useValue: mockEncryptionConfigService, + }, + { + provide: ExchangeClientFactory, + useValue: mockExchangeClientFactory, + }, + ], + }).compile(); + + exchangeApiKeysService = module.get( + ExchangeApiKeysService, + ); + aesEncryptionService = + module.get(AesEncryptionService); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(exchangeApiKeysService).toBeDefined(); + }); + + describe('enroll', () => { + it.each([ + Object.assign(generateExchangeApiKeysData(), { userId: '' }), + Object.assign(generateExchangeApiKeysData(), { apiKey: '' }), + Object.assign(generateExchangeApiKeysData(), { secretKey: '' }), + ])('should throw if required param is missing [%#]', async (input) => { + let thrownError; + try { + await exchangeApiKeysService.enroll(input); + } catch (error) { + thrownError = error; + } + + expect(thrownError.constructor).toBe(Error); + expect(thrownError.message).toBe('Invalid arguments'); + }); + + it('should throw if provided keys do not have required access', async () => { + mockExchangeApiKeysRepository.findOneByUserId.mockResolvedValueOnce(null); + mockExchangeClient.checkRequiredAccess.mockResolvedValueOnce(false); + + const input = generateExchangeApiKeysData(); + + let thrownError; + try { + await exchangeApiKeysService.enroll(input); + } catch (error) { + thrownError = error; + } + + expect(thrownError).toBeInstanceOf(KeyAuthorizationError); + expect(thrownError.exchangeName).toBe(input.exchangeName); + }); + + it('should overwrite existing keys if user already has active ones', async () => { + const input = generateExchangeApiKeysData(); + const existingKey = generateExchangeApiKey(); + mockExchangeApiKeysRepository.findOneByUserId.mockResolvedValueOnce( + existingKey, + ); + mockExchangeClient.checkRequiredAccess.mockResolvedValueOnce(true); + mockUserRepository.findOneById.mockResolvedValueOnce({ + id: input.userId, + } as UserEntity); + mockExchangeApiKeysRepository.updateOne.mockImplementation( + async (entity) => entity, + ); + + const updatedEntity = await exchangeApiKeysService.enroll(input); + + expect(mockExchangeApiKeysRepository.updateOne).toHaveBeenCalledWith( + existingKey, + ); + const [decryptedApiKey, decryptedSecretKey] = await Promise.all([ + aesEncryptionService.decrypt(updatedEntity.apiKey), + aesEncryptionService.decrypt(updatedEntity.secretKey), + ]); + expect(decryptedApiKey.toString()).toBe(input.apiKey); + expect(decryptedSecretKey.toString()).toBe(input.secretKey); + }); + + it('should throw if user not exists', async () => { + mockExchangeApiKeysRepository.findOneByUserId.mockResolvedValueOnce(null); + mockExchangeClient.checkRequiredAccess.mockResolvedValueOnce(true); + + mockUserRepository.findOneById.mockResolvedValueOnce(null); + + const input = generateExchangeApiKeysData(); + + let thrownError; + try { + await exchangeApiKeysService.enroll(input); + } catch (error) { + thrownError = error; + } + + expect(thrownError).toBeInstanceOf(UserNotFoundError); + }); + + it('should insert encrypted keys if data is valid', async () => { + mockExchangeApiKeysRepository.findOneByUserId.mockResolvedValueOnce(null); + mockExchangeClient.checkRequiredAccess.mockResolvedValueOnce(true); + mockUserRepository.findOneById.mockResolvedValueOnce({ + id: 1, + } as UserEntity); + + const input = generateExchangeApiKeysData(); + + const entity = await exchangeApiKeysService.enroll(input); + + expect(entity.userId).toBe(input.userId); + expect(entity.exchangeName).toBe(input.exchangeName); + expect(entity.apiKey).not.toBe(input.apiKey); + expect(entity.secretKey).not.toBe(input.secretKey); + + const [decryptedApiKey, decryptedSecretKey] = await Promise.all([ + aesEncryptionService.decrypt(entity.apiKey), + aesEncryptionService.decrypt(entity.secretKey), + ]); + + expect(decryptedApiKey.toString()).toBe(input.apiKey); + expect(decryptedSecretKey.toString()).toBe(input.secretKey); + }); + }); + + describe('retrieve', () => { + it('should return null if key not found for the user', async () => { + const { userId } = generateExchangeApiKeysData(); + mockExchangeApiKeysRepository.findOneByUserId.mockResolvedValueOnce(null); + + const result = await exchangeApiKeysService.retrieve(userId); + expect(result).toBeNull(); + }); + + it('should return decrypted keys', async () => { + const { userId, exchangeName, apiKey, secretKey } = + generateExchangeApiKeysData(); + + const [encryptedApiKey, encryptedSecretKey] = await Promise.all([ + aesEncryptionService.encrypt(Buffer.from(apiKey)), + aesEncryptionService.encrypt(Buffer.from(secretKey)), + ]); + mockExchangeApiKeysRepository.findOneByUserId.mockResolvedValueOnce({ + exchangeName, + apiKey: encryptedApiKey, + secretKey: encryptedSecretKey, + } as ExchangeApiKeyEntity); + + const result = await exchangeApiKeysService.retrieve(userId); + + expect(result).not.toBeNull(); + expect(result!.apiKey).toBe(apiKey); + expect(result!.secretKey).toBe(secretKey); + expect( + mockExchangeApiKeysRepository.findOneByUserId, + ).toHaveBeenCalledWith(userId); + }); + }); + + describe('getSupportedExchanges', () => { + it('returns a copy of supported exchanges constant', () => { + const result = exchangeApiKeysService.getSupportedExchanges(); + + expect(result).toEqual(SUPPORTED_EXCHANGES_INFO); + expect(result).not.toBe(SUPPORTED_EXCHANGES_INFO); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts new file mode 100644 index 0000000000..c59b852fdc --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/exchange-api-keys.service.ts @@ -0,0 +1,101 @@ +import { Injectable } from '@nestjs/common'; + +import { + SUPPORTED_EXCHANGES_INFO, + SupportedExchange, + type SupportedExchangeInfo, +} from '@/common/constants'; +import { AesEncryptionService } from '@/modules/encryption/aes-encryption.service'; +import { ExchangeClientFactory } from '@/modules/exchange/exchange-client.factory'; +import { UserNotFoundError, UserRepository } from '@/modules/user'; + +import { ExchangeApiKeyEntity } from './exchange-api-key.entity'; +import { KeyAuthorizationError } from './exchange-api-keys.errors'; +import { ExchangeApiKeysRepository } from './exchange-api-keys.repository'; + +@Injectable() +export class ExchangeApiKeysService { + constructor( + private readonly aesEncryptionService: AesEncryptionService, + private readonly exchangeApiKeysRepository: ExchangeApiKeysRepository, + private readonly exchangeClientFactory: ExchangeClientFactory, + private readonly userRepository: UserRepository, + ) {} + + async enroll(input: { + userId: number; + exchangeName: SupportedExchange; + apiKey: string; + secretKey: string; + }): Promise { + const { userId, exchangeName, apiKey, secretKey } = input; + + if (!userId || !apiKey || !secretKey) { + throw new Error('Invalid arguments'); + } + + const currentKeys = + await this.exchangeApiKeysRepository.findOneByUserId(userId); + + const client = await this.exchangeClientFactory.create(exchangeName, { + apiKey, + secretKey, + }); + const hasRequiredAccess = await client.checkRequiredAccess(); + if (!hasRequiredAccess) { + throw new KeyAuthorizationError(exchangeName); + } + + const user = await this.userRepository.findOneById(userId); + if (!user) { + throw new UserNotFoundError(userId); + } + + const [encryptedApiKey, encryptedSecretKey] = await Promise.all([ + this.aesEncryptionService.encrypt(Buffer.from(apiKey)), + this.aesEncryptionService.encrypt(Buffer.from(secretKey)), + ]); + if (currentKeys) { + currentKeys.exchangeName = exchangeName; + currentKeys.apiKey = encryptedApiKey; + currentKeys.secretKey = encryptedSecretKey; + + return this.exchangeApiKeysRepository.updateOne(currentKeys); + } + + const enrolledKey = new ExchangeApiKeyEntity(); + enrolledKey.userId = userId; + enrolledKey.exchangeName = exchangeName; + enrolledKey.apiKey = encryptedApiKey; + enrolledKey.secretKey = encryptedSecretKey; + await this.exchangeApiKeysRepository.createUnique(enrolledKey); + + return enrolledKey; + } + + async retrieve(userId: number): Promise<{ + exchangeName: string; + apiKey: string; + secretKey: string; + } | null> { + const entity = await this.exchangeApiKeysRepository.findOneByUserId(userId); + if (!entity) { + return null; + } + + const [decryptedApiKey, decryptedSecretKey] = await Promise.all([ + this.aesEncryptionService.decrypt(entity.apiKey), + this.aesEncryptionService.decrypt(entity.secretKey), + ]); + + return { + exchangeName: entity.exchangeName, + apiKey: decryptedApiKey.toString(), + secretKey: decryptedSecretKey.toString(), + }; + } + + getSupportedExchanges(): SupportedExchangeInfo[] { + return SUPPORTED_EXCHANGES_INFO.map((exchange) => ({ ...exchange })); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/fixtures/index.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/fixtures/index.ts new file mode 100644 index 0000000000..8597aa47fc --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/fixtures/index.ts @@ -0,0 +1,25 @@ +import { faker } from '@faker-js/faker'; + +import { generateExchangeName } from '@/modules/exchange/fixtures'; + +import { ExchangeApiKeyEntity } from '../exchange-api-key.entity'; + +export function generateExchangeApiKeysData() { + return { + userId: faker.number.int(), + exchangeName: generateExchangeName(), + apiKey: faker.string.sample(), + secretKey: faker.string.sample(), + }; +} + +export function generateExchangeApiKey(): ExchangeApiKeyEntity { + const entity = { + id: faker.number.int(), + ...generateExchangeApiKeysData(), + createdAt: faker.date.recent(), + updatedAt: new Date(), + }; + + return entity as ExchangeApiKeyEntity; +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/index.ts b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/index.ts new file mode 100644 index 0000000000..2736f37d6b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange-api-keys/index.ts @@ -0,0 +1,8 @@ +export { ExchangeApiKeysModule } from './exchange-api-keys.module'; +export { ExchangeApiKeyEntity } from './exchange-api-key.entity'; +export { ExchangeApiKeysRepository } from './exchange-api-keys.repository'; +export { ExchangeApiKeysService } from './exchange-api-keys.service'; +export { + ExchangeApiKeyNotFoundError, + KeyAuthorizationError, +} from './exchange-api-keys.errors'; diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/errors.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/errors.ts new file mode 100644 index 0000000000..d529464ffa --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/errors.ts @@ -0,0 +1,15 @@ +import { BaseError } from '@/common/errors/base'; + +export class ExchangeApiClientError extends BaseError {} + +export class ExchangeProviderResponseError extends BaseError { + constructor(exchange: string, status: number, detail?: string) { + const exchangeLabel = `${exchange.toUpperCase()} API`; + const fallback = status ? `status ${status}` : 'an error'; + super( + detail + ? `${exchangeLabel} error: ${detail}` + : `${exchangeLabel} responded with ${fallback}`, + ); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/exchange-client.factory.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/exchange-client.factory.ts new file mode 100644 index 0000000000..035c2b0ef2 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/exchange-client.factory.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@nestjs/common'; + +import type { SupportedExchange } from '@/common/constants'; + +import { GateExchangeClient } from './gate-exchange.client'; +import { MexcExchangeClient } from './mexc-exchange.client'; +import type { + ExchangeClient, + ExchangeClientCredentials, + ExchangeClientOptions, +} from './types'; + +@Injectable() +export class ExchangeClientFactory { + async create( + exchange: SupportedExchange, + creds: ExchangeClientCredentials, + options?: ExchangeClientOptions, + ): Promise { + switch (exchange) { + case 'mexc': { + return new MexcExchangeClient(creds, options); + } + case 'gate': { + return new GateExchangeClient(creds, options); + } + default: + throw new Error(`Unsupported exchange: ${exchange}`); + } + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/exchange.module.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/exchange.module.ts new file mode 100644 index 0000000000..ddc664fdc8 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/exchange.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { ExchangeClientFactory } from './exchange-client.factory'; + +@Module({ + providers: [ExchangeClientFactory], + exports: [ExchangeClientFactory], +}) +export class ExchangeModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/exchange.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/exchange.ts new file mode 100644 index 0000000000..bca953a18b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/exchange.ts @@ -0,0 +1,32 @@ +import { faker } from '@faker-js/faker'; + +import { SupportedExchange } from '@/common/constants'; + +export function generateGateAccountBalance(tokens: string[] = []) { + if (tokens.length === 0) { + throw new Error('At least one token must be specified'); + } + return tokens.map((token) => ({ + currency: token, + available: faker.finance.amount(), + locked: faker.finance.amount(), + freeze: faker.finance.amount(), + })); +} + +export function generateMexcAccountBalance(tokens: string[] = []) { + if (tokens.length === 0) { + throw new Error('At least one token must be specified'); + } + return { + balances: tokens.map((token) => ({ + asset: token, + free: faker.finance.amount(), + locked: faker.finance.amount(), + })), + }; +} + +export function generateExchangeName() { + return faker.helpers.enumValue(SupportedExchange); +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/index.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/index.ts new file mode 100644 index 0000000000..40165d35a9 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/fixtures/index.ts @@ -0,0 +1 @@ +export * from './exchange'; diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.spec.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.spec.ts new file mode 100644 index 0000000000..9b7b60d150 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.spec.ts @@ -0,0 +1,224 @@ +jest.mock('@/logger'); + +import crypto from 'crypto'; + +import { faker } from '@faker-js/faker'; +import nock from 'nock'; + +import { + ExchangeApiClientError, + ExchangeProviderResponseError, +} from './errors'; +import { generateGateAccountBalance } from './fixtures'; +import { + DEVELOP_GATE_API_BASE_URL, + GateExchangeClient, +} from './gate-exchange.client'; + +describe('GateExchangeClient', () => { + afterAll(() => { + nock.restore(); + }); + + afterEach(() => { + jest.resetAllMocks(); + nock.cleanAll(); + }); + + describe('signGateRequest', () => { + it('returns the expected signature for known input', () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const method = faker.string.sample(); + const path = faker.string.sample(); + const query = faker.string.sample(); + const body = faker.string.sample(); + const now = faker.number.int(); + + const client = new GateExchangeClient({ apiKey, secretKey }); + + jest.useFakeTimers({ now }); + const { signature, timestamp } = client['signGateRequest']( + method, + path, + query, + body, + ); + jest.useRealTimers(); + + const bodyHash = crypto + .createHash('sha512') + .update(body ?? '') + .digest('hex'); + const payload = [ + method, + path, + query, + bodyHash, + String(Math.floor(now / 1000)), + ].join('\n'); + const expectedSignature = crypto + .createHmac('sha512', secretKey) + .update(payload) + .digest('hex'); + + expect(timestamp).toBe(String(Math.floor(now / 1000))); + expect(signature).toBe(expectedSignature); + }); + }); + + describe('constructor', () => { + it('throws if credentials are missing', () => { + expect( + () => new GateExchangeClient({ apiKey: '', secretKey: '' }), + ).toThrow(ExchangeApiClientError); + }); + + it('sets fields correctly', () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const timeoutMs = faker.number.int(); + const client = new GateExchangeClient( + { apiKey, secretKey }, + { timeoutMs: timeoutMs }, + ); + expect(client).toBeDefined(); + expect(client['apiKey']).toBe(apiKey); + expect(client['secretKey']).toBe(secretKey); + expect(client['timeoutMs']).toBe(timeoutMs); + }); + }); + + describe('checkRequiredAccess', () => { + const path = '/spot/accounts'; + + it('returns true if fetch is ok', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .reply(200); + const result = await client.checkRequiredAccess(); + scope.done(); + expect(result).toBe(true); + }); + + it('returns false if fetch is not ok', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .reply(403); + const result = await client.checkRequiredAccess(); + scope.done(); + expect(result).toBe(false); + }); + + it('throws ExchangeApiClientError on fetch error', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .replyWithError('network error'); + let thrownError; + try { + await client.checkRequiredAccess(); + } catch (error) { + thrownError = error; + } + + scope.done(); + + expect(thrownError).toBeInstanceOf(ExchangeApiClientError); + expect((thrownError as Error).message).toBe( + 'Failed to make request for exchange', + ); + }); + }); + + describe('getAccountBalance', () => { + const path = '/spot/accounts'; + + it('throws ExchangeProviderResponseError with response body if fetch not ok', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const errorPayload = { message: 'forbidden' }; + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .reply(403, errorPayload); + + const balancePromise = client.getAccountBalance(asset); + await expect(balancePromise).rejects.toThrow( + ExchangeProviderResponseError, + ); + + scope.done(); + }); + + it('returns 0 if asset not found', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .reply(200, generateGateAccountBalance(['OTHER'])); + const result = await client.getAccountBalance(asset); + scope.done(); + expect(result).toBe(0); + }); + + it('returns sum of available and locked if asset found', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const balanceFixture = generateGateAccountBalance([asset]); + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .reply(200, balanceFixture); + + const result = await client.getAccountBalance(asset); + scope.done(); + expect(result).toBe( + parseFloat(balanceFixture[0].available) + + parseFloat(balanceFixture[0].locked), + ); + }); + + it('throws ExchangeApiClientError on fetch error', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new GateExchangeClient({ apiKey, secretKey }); + const scope = nock(DEVELOP_GATE_API_BASE_URL) + .get(path) + .query(true) + .replyWithError('network error'); + let thrownError; + try { + await client.getAccountBalance(asset); + } catch (error) { + thrownError = error; + } + + scope.done(); + + expect(thrownError).toBeInstanceOf(ExchangeApiClientError); + expect((thrownError as Error).message).toBe( + 'Failed to make request for exchange', + ); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.ts new file mode 100644 index 0000000000..ad50394dea --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/gate-exchange.client.ts @@ -0,0 +1,148 @@ +import { createHash, createHmac } from 'node:crypto'; + +import { SupportedExchange } from '@/common/constants'; +import logger from '@/logger'; +import Environment from '@/utils/environment'; + +import { + ExchangeApiClientError, + ExchangeProviderResponseError, +} from './errors'; +import type { + ExchangeClient, + ExchangeClientCredentials, + ExchangeClientOptions, +} from './types'; +import { fetchWithHandling } from './utils'; + +export const GATE_API_BASE_URL = 'https://api.gateio.ws/api/v4'; +export const DEVELOP_GATE_API_BASE_URL = + 'https://api-testnet.gateapi.io/api/v4'; + +export class GateExchangeClient implements ExchangeClient { + readonly id = SupportedExchange.GATE; + private readonly apiKey: string; + private readonly secretKey: string; + private readonly timeoutMs?: number; + private readonly apiBaseUrl = Environment.isDevelopment() + ? DEVELOP_GATE_API_BASE_URL + : GATE_API_BASE_URL; + private readonly logger = logger.child({ + context: GateExchangeClient.name, + exchange: this.id, + }); + + constructor( + creds: ExchangeClientCredentials, + options?: ExchangeClientOptions, + ) { + if (!creds?.apiKey || !creds?.secretKey) { + throw new ExchangeApiClientError('Incomplete credentials for Gate'); + } + this.apiKey = creds.apiKey; + this.secretKey = creds.secretKey; + this.timeoutMs = options?.timeoutMs; + } + + async checkRequiredAccess(): Promise { + const method = 'GET'; + const path = '/spot/accounts'; + const query = ''; + const body = ''; + const { signature, timestamp } = this.signGateRequest( + method, + `/api/v4${path}`, + query, + body, + ); + + const res = await fetchWithHandling( + `${this.apiBaseUrl}${path}`, + { + KEY: this.apiKey, + SIGN: signature, + Timestamp: timestamp, + Accept: 'application/json', + }, + this.logger, + this.timeoutMs, + ); + + if (res.ok) return true; + return false; + } + + async getAccountBalance(asset: string): Promise { + const method = 'GET'; + const path = '/spot/accounts'; + const query = `currency=${encodeURIComponent(asset)}`; + const body = ''; + const requestPath = `/api/v4${path}`; + const { signature, timestamp } = this.signGateRequest( + method, + requestPath, + query, + body, + ); + const url = `${this.apiBaseUrl}${path}?${query}`; + + const res = await fetchWithHandling( + url, + { + KEY: this.apiKey, + SIGN: signature, + Timestamp: timestamp, + Accept: 'application/json', + }, + this.logger, + this.timeoutMs, + ); + + if (!res.ok) { + const errorBody = await res.json(); + throw new ExchangeProviderResponseError( + this.id, + res.status, + errorBody.message as string, + ); + } + + const data = (await res.json()) as Array<{ + currency: string; + available: string; + locked?: string; + freeze?: string; + }>; + + const normalize = (item: { + currency: string; + available: string; + locked?: string; + freeze?: string; + }) => { + const free = parseFloat(item.available) || 0; + const locked = parseFloat(item.locked ?? item.freeze ?? '0') || 0; + return free + locked; + }; + + const entry = data.find((d) => d.currency === asset); + return entry ? normalize(entry) : 0; + } + + private signGateRequest( + method: string, + path: string, + query: string, + body: string, + ): { signature: string; timestamp: string } { + const timestamp = String(Math.floor(Date.now() / 1000)); + const bodyHash = createHash('sha512') + .update(body ?? '') + .digest('hex'); + const payload = [method, path, query, bodyHash, timestamp].join('\n'); + const signature = createHmac('sha512', this.secretKey) + .update(payload) + .digest('hex'); + return { signature, timestamp }; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/index.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/index.ts new file mode 100644 index 0000000000..3a0424a866 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/index.ts @@ -0,0 +1,3 @@ +export { ExchangeModule } from './exchange.module'; +export { ExchangeClientFactory } from './exchange-client.factory'; +export * from './types'; diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.spec.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.spec.ts new file mode 100644 index 0000000000..5b91f88d3b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.spec.ts @@ -0,0 +1,196 @@ +jest.mock('@/logger'); + +import { createHmac } from 'crypto'; + +import { faker } from '@faker-js/faker'; +import nock from 'nock'; + +import { + ExchangeApiClientError, + ExchangeProviderResponseError, +} from './errors'; +import { generateMexcAccountBalance } from './fixtures'; +import { MexcExchangeClient, MEXC_API_BASE_URL } from './mexc-exchange.client'; + +describe('MexcExchangeClient', () => { + afterAll(() => { + nock.restore(); + }); + + afterEach(() => { + jest.resetAllMocks(); + nock.cleanAll(); + }); + + describe('constructor', () => { + it('throws if credentials are missing', () => { + expect( + () => new MexcExchangeClient({ apiKey: '', secretKey: '' }), + ).toThrow(ExchangeApiClientError); + }); + + it('sets fields correctly', () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const timeoutMs = faker.number.int(); + + const client = new MexcExchangeClient( + { apiKey, secretKey }, + { timeoutMs: timeoutMs }, + ); + + expect(client).toBeDefined(); + expect(client['apiKey']).toBe(apiKey); + expect(client['secretKey']).toBe(secretKey); + expect(client['timeoutMs']).toBe(timeoutMs); + }); + }); + + describe('signQuery', () => { + it('getSignedQuery returns correct structure and signature', () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + + const now = Date.now(); + jest.useFakeTimers({ now }); + const result = client['getSignedQuery'](); + jest.useRealTimers(); + + expect(result).toHaveProperty('query'); + expect(result).toHaveProperty('signature'); + expect(result.query).toBe(`timestamp=${now}&recvWindow=5000`); + + const expectedSignature = createHmac('sha256', secretKey) + .update(result.query) + .digest('hex'); + expect(result.signature).toBe(expectedSignature); + }); + }); + + describe('checkRequiredAccess', () => { + const path = '/account'; + + it('returns true if fetch is ok', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const scope = nock(MEXC_API_BASE_URL).get(path).query(true).reply(200); + const result = await client.checkRequiredAccess(); + scope.done(); + expect(result).toBe(true); + }); + + it('returns false if fetch is not ok', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const scope = nock(MEXC_API_BASE_URL).get(path).query(true).reply(403); + const result = await client.checkRequiredAccess(); + scope.done(); + expect(result).toBe(false); + }); + + it('throws ExchangeApiClientError on fetch error', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const scope = nock(MEXC_API_BASE_URL) + .get(path) + .query(true) + .replyWithError('network error'); + let thrownError: unknown; + try { + await client.checkRequiredAccess(); + } catch (error) { + thrownError = error; + } + + scope.done(); + + expect(thrownError).toBeInstanceOf(ExchangeApiClientError); + expect((thrownError as Error).message).toBe( + 'Failed to make request for exchange', + ); + }); + }); + + describe('getAccountBalance', () => { + const path = '/account'; + + it('throws ExchangeProviderResponseError with response detail if fetch not ok', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const errorPayload = { msg: 'forbidden' }; + const scope = nock(MEXC_API_BASE_URL) + .get(path) + .query(true) + .reply(400, errorPayload); + + const balancePromise = client.getAccountBalance(asset); + await expect(balancePromise).rejects.toThrow( + ExchangeProviderResponseError, + ); + + scope.done(); + }); + + it('returns 0 if asset not found', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const scope = nock(MEXC_API_BASE_URL) + .get(path) + .query(true) + .reply(200, generateMexcAccountBalance(['OTHER'])); + const result = await client.getAccountBalance(asset); + scope.done(); + expect(result).toBe(0); + }); + + it('returns sum of free and locked if asset found', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const balanceFixture = generateMexcAccountBalance([asset]); + const scope = nock(MEXC_API_BASE_URL) + .get(path) + .query(true) + .reply(200, balanceFixture); + const result = await client.getAccountBalance(asset); + scope.done(); + expect(result).toBe( + parseFloat(balanceFixture.balances[0].free) + + parseFloat(balanceFixture.balances[0].locked), + ); + }); + + it('throws ExchangeApiClientError on fetch error', async () => { + const apiKey = faker.string.sample(); + const secretKey = faker.string.sample(); + const asset = faker.finance.currencyCode(); + const client = new MexcExchangeClient({ apiKey, secretKey }); + const scope = nock(MEXC_API_BASE_URL) + .get(path) + .query(true) + .replyWithError('network error'); + let thrownError: unknown; + try { + await client.getAccountBalance(asset); + } catch (error) { + thrownError = error; + } + + scope.done(); + + expect(thrownError).toBeInstanceOf(ExchangeApiClientError); + expect((thrownError as Error).message).toBe( + 'Failed to make request for exchange', + ); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.ts new file mode 100644 index 0000000000..9c3b0d4460 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/mexc-exchange.client.ts @@ -0,0 +1,101 @@ +import { createHmac } from 'node:crypto'; + +import { SupportedExchange } from '@/common/constants'; +import logger from '@/logger'; + +import { + ExchangeApiClientError, + ExchangeProviderResponseError, +} from './errors'; +import type { + ExchangeClient, + ExchangeClientCredentials, + ExchangeClientOptions, +} from './types'; +import { fetchWithHandling } from './utils'; + +export const MEXC_API_BASE_URL = 'https://api.mexc.com/api/v3'; + +export class MexcExchangeClient implements ExchangeClient { + readonly id = SupportedExchange.MEXC; + private readonly apiKey: string; + private readonly secretKey: string; + private readonly timeoutMs?: number; + private readonly logger = logger.child({ + context: MexcExchangeClient.name, + exchange: this.id, + }); + readonly recvWindow = 5000; + + constructor( + creds: ExchangeClientCredentials, + options?: ExchangeClientOptions, + ) { + if (!creds?.apiKey || !creds?.secretKey) { + throw new ExchangeApiClientError('Incomplete credentials for MEXC'); + } + this.apiKey = creds.apiKey; + this.secretKey = creds.secretKey; + this.timeoutMs = options?.timeoutMs; + } + + private signQuery(query: string): string { + return createHmac('sha256', this.secretKey).update(query).digest('hex'); + } + + async checkRequiredAccess(): Promise { + const path = '/account'; + const { query, signature } = this.getSignedQuery(); + const url = `${MEXC_API_BASE_URL}${path}?${query}&signature=${signature}`; + + const res = await fetchWithHandling( + url, + { 'X-MEXC-APIKEY': this.apiKey }, + this.logger, + this.timeoutMs, + ); + if (res.ok) return true; + return false; + } + + async getAccountBalance(asset: string): Promise { + const path = '/account'; + const { query, signature } = this.getSignedQuery(); + const url = `${MEXC_API_BASE_URL}${path}?${query}&signature=${signature}`; + + const res = await fetchWithHandling( + url, + { 'X-MEXC-APIKEY': this.apiKey }, + this.logger, + this.timeoutMs, + ); + if (!res.ok) { + const errorBody = await res.json(); + throw new ExchangeProviderResponseError( + this.id, + res.status, + errorBody.msg as string, + ); + } + const data = (await res.json()) as { + balances?: Array<{ asset: string; free: string; locked: string }>; + }; + const balances = data.balances || []; + const entry = balances.find((b) => b.asset === asset); + if (!entry) return 0; + const total = + (parseFloat(entry.free || '0') || 0) + + (parseFloat(entry.locked || '0') || 0); + return total; + } + + private getSignedQuery(): { + query: string; + signature: string; + } { + const timestamp = Date.now(); + const query = `timestamp=${timestamp}&recvWindow=${this.recvWindow}`; + const signature = this.signQuery(query); + return { query, signature }; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/types.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/types.ts new file mode 100644 index 0000000000..1fd5cfa68b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/types.ts @@ -0,0 +1,16 @@ +import type { SupportedExchange } from '@/common/constants'; + +export interface ExchangeClientCredentials { + apiKey: string; + secretKey: string; +} + +export interface ExchangeClientOptions { + timeoutMs?: number; +} + +export interface ExchangeClient { + readonly id: SupportedExchange; + checkRequiredAccess(): Promise; + getAccountBalance(asset: string): Promise; +} diff --git a/packages/apps/reputation-oracle/server/src/modules/exchange/utils.ts b/packages/apps/reputation-oracle/server/src/modules/exchange/utils.ts new file mode 100644 index 0000000000..8a2fd42fdc --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/exchange/utils.ts @@ -0,0 +1,27 @@ +import { DEFAULT_TIMEOUT_MS } from '@/common/constants'; +import Logger from '@/logger'; + +import { ExchangeApiClientError } from './errors'; + +export async function fetchWithHandling( + url: string, + headers: HeadersInit, + logger: typeof Logger, + timeoutMs?: number, +): Promise { + try { + const res = await fetch(url, { + method: 'GET', + headers, + signal: AbortSignal.timeout(timeoutMs || DEFAULT_TIMEOUT_MS), + }); + return res; + } catch (error) { + const message: string = `Failed to make request for exchange`; + logger.error(message, { + url, + error, + }); + throw new ExchangeApiClientError(message); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/index.ts b/packages/apps/reputation-oracle/server/src/modules/staking/index.ts new file mode 100644 index 0000000000..fc1296365f --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/index.ts @@ -0,0 +1,3 @@ +export { StakingModule } from './staking.module'; +export { StakingService } from './staking.service'; +export type { StakeSummaryData } from './types'; diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.controller.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.controller.ts new file mode 100644 index 0000000000..c4f711281d --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.controller.ts @@ -0,0 +1,39 @@ +import { Controller, Get, Req, UseFilters } from '@nestjs/common'; +import { + ApiBearerAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; + +import { Public } from '@/common/decorators'; +import type { RequestWithUser } from '@/common/types'; + +import { StakeConfigResponseDto, StakeSummaryResponseDto } from './staking.dto'; +import { StakingControllerErrorsFilter } from './staking.error-filter'; +import { StakingService } from './staking.service'; + +@ApiTags('Staking') +@UseFilters(StakingControllerErrorsFilter) +@Controller('staking') +export class StakingController { + constructor(private readonly stakingService: StakingService) {} + + @ApiBearerAuth() + @ApiOperation({ summary: 'Retrieve aggregated staking info' }) + @ApiResponse({ status: 200, type: StakeSummaryResponseDto }) + @Get('/summary') + async getStakeSummary( + @Req() request: RequestWithUser, + ): Promise { + return this.stakingService.getStakeSummary(request.user.id); + } + + @Public() + @ApiOperation({ summary: 'Retrieve staking configuration' }) + @ApiResponse({ status: 200, type: StakeConfigResponseDto }) + @Get('/config') + async getStakeConfig(): Promise { + return this.stakingService.getStakeConfig(); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.dto.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.dto.ts new file mode 100644 index 0000000000..114430a9da --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.dto.ts @@ -0,0 +1,23 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; + +export class StakeSummaryResponseDto { + @ApiProperty({ name: 'exchange_stake' }) + exchangeStake: string; + + @ApiProperty({ name: 'on_chain_stake' }) + onChainStake: string; + + @ApiPropertyOptional({ name: 'exchange_error' }) + exchangeError?: string; + + @ApiPropertyOptional({ name: 'on_chain_error' }) + onChainError?: string; +} + +export class StakeConfigResponseDto { + @ApiProperty({ name: 'min_threshold' }) + minThreshold: string; + + @ApiProperty({ name: 'eligibility_enabled' }) + eligibilityEnabled: boolean; +} diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.error-filter.ts new file mode 100644 index 0000000000..af660d4d70 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.error-filter.ts @@ -0,0 +1,34 @@ +import { + ArgumentsHost, + Catch, + ExceptionFilter, + HttpStatus, +} from '@nestjs/common'; +import { Request, Response } from 'express'; + +import logger from '@/logger'; +import { UserNotFoundError } from '@/modules/user'; + +@Catch(UserNotFoundError) +export class StakingControllerErrorsFilter implements ExceptionFilter { + private readonly logger = logger.child({ + context: StakingControllerErrorsFilter.name, + }); + + catch(exception: Error, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + let status = HttpStatus.INTERNAL_SERVER_ERROR; + + if (exception instanceof UserNotFoundError) { + status = HttpStatus.UNPROCESSABLE_ENTITY; + } + + return response.status(status).json({ + message: exception.message, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.module.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.module.ts new file mode 100644 index 0000000000..a28244e510 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; + +import { ExchangeModule } from '@/modules/exchange/exchange.module'; +import { ExchangeApiKeysModule } from '@/modules/exchange-api-keys'; +import { UserModule } from '@/modules/user'; +import { Web3Module } from '@/modules/web3'; + +import { StakingController } from './staking.controller'; +import { StakingService } from './staking.service'; + +@Module({ + imports: [ExchangeApiKeysModule, ExchangeModule, UserModule, Web3Module], + providers: [StakingService], + controllers: [StakingController], + exports: [StakingService], +}) +export class StakingModule {} diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts new file mode 100644 index 0000000000..bac6576a7b --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts @@ -0,0 +1,212 @@ +jest.mock('@human-protocol/sdk'); + +import { faker } from '@faker-js/faker'; +import { createMock } from '@golevelup/ts-jest'; +import { StakingClient } from '@human-protocol/sdk'; +import { Test, TestingModule } from '@nestjs/testing'; +import { ethers } from 'ethers'; + +import { SupportedExchange } from '@/common/constants'; +import { StakingConfigService, Web3ConfigService } from '@/config'; +import { type ExchangeClient, ExchangeClientFactory } from '@/modules/exchange'; +import { ExchangeApiKeysService } from '@/modules/exchange-api-keys'; +import { UserEntity, UserNotFoundError, UserRepository } from '@/modules/user'; +import { WalletWithProvider, Web3Service } from '@/modules/web3'; +import { mockWeb3ConfigService } from '@/modules/web3/fixtures'; + +import { StakingService } from './staking.service'; + +const mockExchangeApiKeysService = createMock(); +const mockExchangeClientFactory = { + create: jest.fn(), +}; +const mockExchangeClient = createMock(); +const mockUserRepository = createMock(); +const mockWeb3Service = createMock(); +const mockStakingConfigService: Omit = { + eligibilityEnabled: true, + minThreshold: faker.number.int({ min: 1, max: 1000 }), + asset: 'HMT', + timeoutMs: faker.number.int({ min: 1000, max: 10000 }), +}; +const mockedStakingClient = jest.mocked(StakingClient); + +describe('StakingService', () => { + let stakingService: StakingService; + + beforeAll(async () => { + mockExchangeClientFactory.create.mockResolvedValue(mockExchangeClient); + mockExchangeClient.getAccountBalance.mockReset(); + mockWeb3Service.getSigner.mockReturnValue({ + provider: {}, + } as never); + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + StakingService, + { + provide: ExchangeApiKeysService, + useValue: mockExchangeApiKeysService, + }, + { + provide: ExchangeClientFactory, + useValue: mockExchangeClientFactory, + }, + { provide: UserRepository, useValue: mockUserRepository }, + { provide: Web3Service, useValue: mockWeb3Service }, + { provide: StakingConfigService, useValue: mockStakingConfigService }, + { provide: Web3ConfigService, useValue: mockWeb3ConfigService }, + ], + }).compile(); + + stakingService = module.get(StakingService); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + describe('getExchangeStakedBalance', () => { + const userId = faker.number.int(); + it('returns 0 when user has no exchange keys', async () => { + mockExchangeApiKeysService.retrieve.mockResolvedValueOnce(null); + + await expect( + stakingService.getExchangeStakedBalance(userId), + ).resolves.toBe(0); + }); + + it('returns balance fetched from exchange client', async () => { + const keys = { + exchangeName: SupportedExchange.GATE, + apiKey: faker.string.sample(), + secretKey: faker.string.sample(), + }; + const balance = faker.number.int(); + mockExchangeApiKeysService.retrieve.mockResolvedValueOnce(keys); + mockExchangeClient.getAccountBalance.mockResolvedValueOnce(balance); + + const result = await stakingService.getExchangeStakedBalance(userId); + expect(mockExchangeClientFactory.create).toHaveBeenCalledWith( + keys.exchangeName, + { + apiKey: keys.apiKey, + secretKey: keys.secretKey, + }, + { timeoutMs: mockStakingConfigService.timeoutMs }, + ); + expect(mockExchangeClient.getAccountBalance).toHaveBeenCalledWith( + mockStakingConfigService.asset, + ); + expect(result).toBe(balance); + }); + }); + + describe('getStakeSummary', () => { + const user = { + id: faker.number.int(), + evmAddress: faker.finance.ethereumAddress(), + }; + const onChainStake = faker.number.int(); + const exchangeStake = faker.number.int(); + let spyOnGetExchangeStakedBalance: jest.SpyInstance; + let spyOnGetOnChainStakedBalance: jest.SpyInstance; + + beforeAll(() => { + spyOnGetExchangeStakedBalance = jest + .spyOn(stakingService, 'getExchangeStakedBalance') + .mockImplementation(); + spyOnGetOnChainStakedBalance = jest + .spyOn(stakingService, 'getOnChainStakedBalance') + .mockImplementation(); + }); + + afterAll(() => { + spyOnGetExchangeStakedBalance.mockRestore(); + spyOnGetOnChainStakedBalance.mockRestore(); + }); + + it('throws when user is not found', async () => { + mockUserRepository.findOneById.mockResolvedValueOnce(null); + + await expect( + stakingService.getStakeSummary(user.id), + ).rejects.toBeInstanceOf(UserNotFoundError); + }); + + it('returns aggregated exchange and on-chain stakes', async () => { + mockUserRepository.findOneById.mockResolvedValueOnce(user as UserEntity); + spyOnGetExchangeStakedBalance.mockResolvedValueOnce(exchangeStake); + spyOnGetOnChainStakedBalance.mockResolvedValueOnce(onChainStake); + + const result = await stakingService.getStakeSummary(user.id); + + expect(spyOnGetExchangeStakedBalance).toHaveBeenCalledWith(user.id); + expect(spyOnGetOnChainStakedBalance).toHaveBeenCalledWith( + user.evmAddress, + ); + expect(result).toEqual({ + exchangeStake: exchangeStake.toString(), + onChainStake: onChainStake.toString(), + }); + }); + + it('skips on-chain lookup when user has no address', async () => { + mockUserRepository.findOneById.mockResolvedValueOnce({ + ...user, + evmAddress: null, + } as UserEntity); + spyOnGetExchangeStakedBalance.mockResolvedValueOnce(exchangeStake); + + const result = await stakingService.getStakeSummary(user.id); + + expect(spyOnGetOnChainStakedBalance).not.toHaveBeenCalled(); + expect(result).toEqual({ + exchangeStake: exchangeStake.toString(), + onChainStake: '0', + }); + }); + }); + + describe('getOnChainStakedBalance', () => { + it('returns total staked and locked balance', async () => { + const address = faker.finance.ethereumAddress(); + const stakedAmount = ethers.toBigInt( + faker.number.int({ min: 500, max: 1000000 }), + ); + const lockedAmount = ethers.toBigInt( + faker.number.int({ min: 500, max: 999999 }), + ); + const mockProvider = {}; + mockWeb3Service.getSigner.mockReturnValueOnce({ + provider: mockProvider, + } as WalletWithProvider); + + const getStakerInfoMock = jest + .fn() + .mockResolvedValue({ stakedAmount, lockedAmount }); + mockedStakingClient.build.mockResolvedValueOnce({ + getStakerInfo: getStakerInfoMock, + } as unknown as StakingClient); + + const result = await stakingService.getOnChainStakedBalance(address); + + expect(mockedStakingClient.build).toHaveBeenCalledWith(mockProvider); + expect(getStakerInfoMock).toHaveBeenCalledWith(address); + expect(result).toBe( + Number(ethers.formatEther(stakedAmount + lockedAmount)), + ); + }); + }); + + describe('getStakeConfig', () => { + it('returns current staking configuration', async () => { + const result = await stakingService.getStakeConfig(); + + expect(result).toEqual({ + minThreshold: mockStakingConfigService.minThreshold.toString(), + eligibilityEnabled: mockStakingConfigService.eligibilityEnabled, + }); + }); + }); +}); diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts new file mode 100644 index 0000000000..b99412ddb0 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts @@ -0,0 +1,112 @@ +import { StakingClient } from '@human-protocol/sdk'; +import { Injectable } from '@nestjs/common'; +import { ethers } from 'ethers'; + +import { SupportedExchange } from '@/common/constants'; +import { StakingConfigService, Web3ConfigService } from '@/config'; +import logger from '@/logger'; +import { ExchangeClientFactory } from '@/modules/exchange/exchange-client.factory'; +import { ExchangeApiKeysService } from '@/modules/exchange-api-keys'; +import { UserNotFoundError, UserRepository } from '@/modules/user'; +import { Web3Service } from '@/modules/web3'; +import { formatStake } from '@/utils/stake'; + +import { StakeConfigData, StakeSummaryData } from './types'; + +@Injectable() +export class StakingService { + private readonly logger = logger.child({ + context: StakingService.name, + }); + + constructor( + private readonly exchangeApiKeysService: ExchangeApiKeysService, + private readonly exchangeClientFactory: ExchangeClientFactory, + private readonly userRepository: UserRepository, + private readonly web3Service: Web3Service, + private readonly stakingConfigService: StakingConfigService, + private readonly web3ConfigService: Web3ConfigService, + ) {} + + async getExchangeStakedBalance(userId: number): Promise { + const apiKeys = await this.exchangeApiKeysService.retrieve(userId); + if (!apiKeys) { + return 0; + } + + const client = await this.exchangeClientFactory.create( + apiKeys.exchangeName as SupportedExchange, + { + apiKey: apiKeys.apiKey, + secretKey: apiKeys.secretKey, + }, + { timeoutMs: this.stakingConfigService.timeoutMs }, + ); + + return client.getAccountBalance(this.stakingConfigService.asset); + } + + async getOnChainStakedBalance(address: string): Promise { + const chainId = this.web3ConfigService.reputationNetworkChainId; + const provider = this.web3Service.getSigner(chainId).provider; + + const stakingClient = await StakingClient.build(provider); + const stakerInfo = await stakingClient.getStakerInfo(address); + + const total = + (stakerInfo.stakedAmount ?? 0n) + (stakerInfo.lockedAmount ?? 0n); + return Number(ethers.formatEther(total)); + } + + async getStakeSummary(userId: number): Promise { + const user = await this.userRepository.findOneById(userId); + if (!user) { + throw new UserNotFoundError(userId); + } + + const summary: StakeSummaryData = { + exchangeStake: '0', + onChainStake: '0', + }; + + try { + summary.exchangeStake = formatStake( + await this.getExchangeStakedBalance(userId), + ); + } catch (error) { + summary.exchangeError = error.message + ? error.message + : 'Unable to fetch exchange stake'; + this.logger.warn('Failed to retrieve exchange stake', { + userId, + error, + }); + } + + if (user.evmAddress) { + try { + summary.onChainStake = formatStake( + await this.getOnChainStakedBalance(user.evmAddress), + ); + } catch (error) { + summary.onChainError = error.message + ? error.message + : 'Unable to fetch on-chain stake'; + this.logger.warn('Failed to retrieve on-chain stake', { + userId, + evmAddress: user.evmAddress, + error, + }); + } + } + + return summary; + } + + async getStakeConfig(): Promise { + return { + minThreshold: this.stakingConfigService.minThreshold.toString(), + eligibilityEnabled: this.stakingConfigService.eligibilityEnabled, + }; + } +} diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/types.ts b/packages/apps/reputation-oracle/server/src/modules/staking/types.ts new file mode 100644 index 0000000000..fcf1e16436 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/modules/staking/types.ts @@ -0,0 +1,11 @@ +export type StakeSummaryData = { + exchangeStake: string; + onChainStake: string; + exchangeError?: string; + onChainError?: string; +}; + +export type StakeConfigData = { + minThreshold: string; + eligibilityEnabled: boolean; +}; diff --git a/packages/apps/reputation-oracle/server/src/modules/web3/web3.service.ts b/packages/apps/reputation-oracle/server/src/modules/web3/web3.service.ts index baa5f64a5f..768196b62a 100644 --- a/packages/apps/reputation-oracle/server/src/modules/web3/web3.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/web3/web3.service.ts @@ -4,6 +4,7 @@ import { Injectable } from '@nestjs/common'; import { Wallet, ethers } from 'ethers'; import { Web3ConfigService, Web3Network } from '@/config'; +import logger from '@/logger'; import type { Chain, WalletWithProvider } from './types'; @@ -22,6 +23,9 @@ export class Web3Service { private signersByChainId: { [chainId: number]: WalletWithProvider; } = {}; + private readonly logger = logger.child({ + context: Web3Service.name, + }); constructor(private readonly web3ConfigService: Web3ConfigService) { const privateKey = this.web3ConfigService.privateKey; diff --git a/packages/apps/reputation-oracle/server/src/utils/stake.ts b/packages/apps/reputation-oracle/server/src/utils/stake.ts new file mode 100644 index 0000000000..49988b7c22 --- /dev/null +++ b/packages/apps/reputation-oracle/server/src/utils/stake.ts @@ -0,0 +1,6 @@ +const stakeFormatter = new Intl.NumberFormat(undefined, { + maximumFractionDigits: 18, + notation: 'standard', + useGrouping: false, +}); +export const formatStake = (value: number) => stakeFormatter.format(value); From 7ded32bd284462855246220c7e2787802782124e Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Mon, 5 Jan 2026 17:57:55 +0300 Subject: [PATCH 15/21] [Logger] fix: logger name in child loggers (#3733) --- .changeset/shy-bikes-roll.md | 6 ++++++ packages/libs/logger/src/abstract-logger.ts | 7 +++++-- packages/libs/logger/src/types.ts | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 .changeset/shy-bikes-roll.md diff --git a/.changeset/shy-bikes-roll.md b/.changeset/shy-bikes-roll.md new file mode 100644 index 0000000000..cb2c0950a1 --- /dev/null +++ b/.changeset/shy-bikes-roll.md @@ -0,0 +1,6 @@ +--- +"@human-protocol/logger": minor +--- + +fix: logger name in child loggers +feat: logger name is public readonly diff --git a/packages/libs/logger/src/abstract-logger.ts b/packages/libs/logger/src/abstract-logger.ts index fdba1c06d7..ca4802efca 100644 --- a/packages/libs/logger/src/abstract-logger.ts +++ b/packages/libs/logger/src/abstract-logger.ts @@ -55,7 +55,7 @@ function serializeError(error: ErrorLike) { abstract class LoggerWrapper implements Logger { protected readonly bindings: LogMeta; - private readonly name?: string; + readonly name?: string; constructor(bindings: LogMeta = {}) { if (!isPlainObject(bindings)) { @@ -92,7 +92,10 @@ abstract class LoggerWrapper implements Logger { throw new Error('Log bindings required for child logger'); } - return this.createChild(bindings); + return this.createChild({ + name: this.name, + ...bindings, + }); } protected abstract createChild(bindings: LogMeta): Logger; diff --git a/packages/libs/logger/src/types.ts b/packages/libs/logger/src/types.ts index 106be0c921..01ee944f02 100644 --- a/packages/libs/logger/src/types.ts +++ b/packages/libs/logger/src/types.ts @@ -23,6 +23,7 @@ type LogFn = { export type ChildBindings = { name?: string } & LogMeta; export interface Logger { + name?: string; debug: LogFn; info: LogFn; warn: LogFn; From 8a2d5162701794804b44d90d225ed4ba7e5dae4c Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Wed, 7 Jan 2026 16:56:07 +0300 Subject: [PATCH 16/21] feat: handle invalid address in signature check (#3734) --- .../src/common/guards/signature.auth.spec.ts | 53 +++++++++++++------ .../src/common/guards/signature.auth.ts | 19 ++++++- .../src/common/guards/signature.auth.spec.ts | 20 +++---- .../src/common/guards/signature.auth.ts | 14 ++++- .../src/common/guards/signature.auth.spec.ts | 14 ++--- .../src/common/guards/signature.auth.ts | 12 ++++- .../src/common/guards/signature.auth.spec.ts | 32 +++++++++++ .../src/common/guards/signature.auth.ts | 3 +- 8 files changed, 128 insertions(+), 39 deletions(-) diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.spec.ts b/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.spec.ts index b841851d89..b100c06851 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.spec.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.spec.ts @@ -1,7 +1,9 @@ +import { faker } from '@faker-js/faker'; import { ChainId, EscrowUtils } from '@human-protocol/sdk'; -import { ExecutionContext } from '@nestjs/common'; +import { ExecutionContext, HttpException } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { Test, TestingModule } from '@nestjs/testing'; + import { AssignmentRepository } from '../../modules/assignment/assignment.repository'; import { HEADER_SIGNATURE_KEY } from '../constant'; import { AuthSignatureRole } from '../enums/role'; @@ -44,6 +46,8 @@ describe('SignatureAuthGuard', () => { guard = module.get(SignatureAuthGuard); reflector = module.get(Reflector); + + (EscrowUtils.getEscrow as jest.Mock).mockClear(); }); it('should be defined', () => { @@ -72,8 +76,9 @@ describe('SignatureAuthGuard', () => { .mockReturnValue([AuthSignatureRole.JobLauncher]); mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; + const mockEscrowAddress = faker.finance.ethereumAddress(); mockRequest.body = { - escrow_address: '0x123', + escrow_address: mockEscrowAddress, chain_id: ChainId.LOCALHOST, }; (verifySignature as jest.Mock).mockReturnValue(true); @@ -82,7 +87,7 @@ describe('SignatureAuthGuard', () => { expect(result).toBeTruthy(); expect(EscrowUtils.getEscrow).toHaveBeenCalledWith( ChainId.LOCALHOST, - '0x123', + mockEscrowAddress, ); }); @@ -93,7 +98,7 @@ describe('SignatureAuthGuard', () => { mockRequest.headers[HEADER_SIGNATURE_KEY] = 'invalidSignature'; mockRequest.body = { - escrow_address: '0x123', + escrow_address: faker.finance.ethereumAddress(), chain_id: ChainId.LOCALHOST, }; (verifySignature as jest.Mock).mockReturnValue(false); @@ -105,8 +110,9 @@ describe('SignatureAuthGuard', () => { reflector.get = jest.fn().mockReturnValue([AuthSignatureRole.Worker]); mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; + const assignmentId = faker.number.int(); mockRequest.body = { - assignment_id: '1', + assignment_id: assignmentId, }; (verifySignature as jest.Mock).mockReturnValue(true); assignmentRepository.findOneById.mockResolvedValue({ @@ -115,10 +121,10 @@ describe('SignatureAuthGuard', () => { const result = await guard.canActivate(context); expect(result).toBeTruthy(); - expect(assignmentRepository.findOneById).toHaveBeenCalledWith('1'); + expect(assignmentRepository.findOneById).toHaveBeenCalledWith(assignmentId); }); - it('should throw AuthError if assignment is not found for Worker role', async () => { + it('should throw BadRequest error if assignment id is not number', async () => { reflector.get = jest.fn().mockReturnValue([AuthSignatureRole.Worker]); mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; @@ -128,6 +134,21 @@ describe('SignatureAuthGuard', () => { (verifySignature as jest.Mock).mockReturnValue(true); assignmentRepository.findOneById.mockResolvedValue(null); + const resultPromise = guard.canActivate(context); + await expect(resultPromise).rejects.toBeInstanceOf(HttpException); + await expect(resultPromise).rejects.toThrow('Invalid assignment id'); + }); + + it('should throw AuthError if assignment is not found for Worker role', async () => { + reflector.get = jest.fn().mockReturnValue([AuthSignatureRole.Worker]); + + mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; + mockRequest.body = { + assignment_id: 1, + }; + (verifySignature as jest.Mock).mockReturnValue(true); + assignmentRepository.findOneById.mockResolvedValue(null); + const resultPromise = guard.canActivate(context); await expect(resultPromise).rejects.toBeInstanceOf(ValidationError); await expect(resultPromise).rejects.toThrow(ErrorAssignment.NotFound); @@ -138,27 +159,29 @@ describe('SignatureAuthGuard', () => { .fn() .mockReturnValue([ AuthSignatureRole.JobLauncher, - AuthSignatureRole.Worker, + AuthSignatureRole.Recording, ]); mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; + const mockEscrowAddress = faker.finance.ethereumAddress(); mockRequest.body = { - escrow_address: '0x123', + escrow_address: mockEscrowAddress, chain_id: ChainId.LOCALHOST, assignment_id: '1', }; (verifySignature as jest.Mock).mockReturnValue(true); - assignmentRepository.findOneById.mockResolvedValue({ - workerAddress: '0xworkerAddress', - } as any); const result = await guard.canActivate(context); expect(result).toBeTruthy(); expect(EscrowUtils.getEscrow).toHaveBeenCalledWith( ChainId.LOCALHOST, - '0x123', + mockEscrowAddress, + ); + expect(verifySignature).toHaveBeenLastCalledWith( + mockRequest.body, + mockRequest.headers[HEADER_SIGNATURE_KEY], + [expect.any(String), expect.any(String)], ); - expect(assignmentRepository.findOneById).toHaveBeenCalledWith('1'); }); it('should throw ValidationError when escrow data is missing', async () => { @@ -170,7 +193,7 @@ describe('SignatureAuthGuard', () => { mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; mockRequest.body = { - escrow_address: '0x123', + escrow_address: faker.finance.ethereumAddress(), chain_id: ChainId.LOCALHOST, }; diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts b/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts index acda7c5d31..3a200da7dc 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts @@ -1,6 +1,13 @@ import { EscrowUtils } from '@human-protocol/sdk'; -import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import { + CanActivate, + ExecutionContext, + HttpException, + HttpStatus, + Injectable, +} from '@nestjs/common'; import { Reflector } from '@nestjs/core'; +import { ethers } from 'ethers'; import { AssignmentRepository } from '../../modules/assignment/assignment.repository'; import { HEADER_SIGNATURE_KEY } from '../constant'; @@ -26,12 +33,18 @@ export class SignatureAuthGuard implements CanActivate { context.getHandler(), ); if (!roles) throw new Error(ErrorSignature.MissingRoles); + const request = context.switchToHttp().getRequest(); const data = request.body; + const signature = request.headers[HEADER_SIGNATURE_KEY]; const oracleAdresses: string[] = []; if (roles.includes(AuthSignatureRole.Worker)) { + if (!Number.isInteger(data.assignment_id)) { + throw new HttpException('Invalid assignment id', HttpStatus.BAD_REQUEST); + } + const assignment = await this.assignmentRepository.findOneById( data.assignment_id, ); @@ -41,6 +54,10 @@ export class SignatureAuthGuard implements CanActivate { throw new ValidationError(ErrorAssignment.NotFound); } } else { + if (!data.chain_id || !ethers.isAddress(data.escrow_address)) { + throw new HttpException('Invalid payload', HttpStatus.BAD_REQUEST); + } + const escrowData = await EscrowUtils.getEscrow( data.chain_id, data.escrow_address, diff --git a/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.spec.ts b/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.spec.ts index dccd6028e6..82e01e8019 100644 --- a/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.spec.ts +++ b/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.spec.ts @@ -52,8 +52,13 @@ describe('SignatureAuthGuard', () => { mockRequest = { switchToHttp: jest.fn().mockReturnThis(), getRequest: jest.fn().mockReturnThis(), - headers: {}, - body: {}, + headers: { + [HEADER_SIGNATURE_KEY]: 'validSignature', + }, + body: { + escrow_address: MOCK_ADDRESS, + chain_id: ChainId.LOCALHOST, + }, originalUrl: '', }; context = { @@ -63,11 +68,6 @@ describe('SignatureAuthGuard', () => { }); it('should return true if signature is verified', async () => { - mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; - mockRequest.body = { - escrow_address: MOCK_ADDRESS, - chain_id: ChainId.LOCALHOST, - }; (verifySignature as jest.Mock).mockReturnValue(true); const result = await guard.canActivate(context as any); @@ -96,12 +96,6 @@ describe('SignatureAuthGuard', () => { it("should throw ValidationError('Escrow not found') when escrow data is missing", async () => { (EscrowUtils.getEscrow as jest.Mock).mockResolvedValueOnce(null); - mockRequest.headers[HEADER_SIGNATURE_KEY] = 'validSignature'; - mockRequest.body = { - escrow_address: MOCK_ADDRESS, - chain_id: ChainId.LOCALHOST, - }; - let thrownError: any; try { await guard.canActivate(context as any); diff --git a/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.ts b/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.ts index 5b2b7451a7..53934dbee6 100644 --- a/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.ts +++ b/packages/apps/fortune/recording-oracle/src/common/guards/signature.auth.ts @@ -1,5 +1,13 @@ import { EscrowUtils } from '@human-protocol/sdk'; -import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import { + CanActivate, + ExecutionContext, + HttpException, + HttpStatus, + Injectable, +} from '@nestjs/common'; +import { ethers } from 'ethers'; + import { HEADER_SIGNATURE_KEY } from '../constants'; import { Role } from '../enums/role'; import { AuthError, ValidationError } from '../errors'; @@ -13,6 +21,10 @@ export class SignatureAuthGuard implements CanActivate { const request = context.switchToHttp().getRequest(); const data = request.body; + if (!data.chain_id || !ethers.isAddress(data.escrow_address)) { + throw new HttpException('Invalid payload', HttpStatus.BAD_REQUEST); + } + const signature = request.headers[HEADER_SIGNATURE_KEY]; const oracleAdresses: string[] = []; try { diff --git a/packages/apps/job-launcher/server/src/common/guards/signature.auth.spec.ts b/packages/apps/job-launcher/server/src/common/guards/signature.auth.spec.ts index a3eab12d9e..1ef8e76746 100644 --- a/packages/apps/job-launcher/server/src/common/guards/signature.auth.spec.ts +++ b/packages/apps/job-launcher/server/src/common/guards/signature.auth.spec.ts @@ -52,8 +52,13 @@ describe('SignatureAuthGuard', () => { mockRequest = { switchToHttp: jest.fn().mockReturnThis(), getRequest: jest.fn().mockReturnThis(), - headers: {}, - body: {}, + headers: { + ['header-signature-key']: 'validSignature', + }, + body: { + escrow_address: MOCK_ADDRESS, + chain_id: ChainId.LOCALHOST, + }, originalUrl: '', }; context = { @@ -63,11 +68,6 @@ describe('SignatureAuthGuard', () => { }); it('should return true if signature is verified', async () => { - mockRequest.headers['header-signature-key'] = 'validSignature'; - mockRequest.body = { - escrow_address: MOCK_ADDRESS, - chain_id: ChainId.LOCALHOST, - }; (verifySignature as jest.Mock).mockReturnValue(true); const result = await guard.canActivate(context as any); diff --git a/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts b/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts index a3c2d11ac5..0c6324f3fe 100644 --- a/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts +++ b/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts @@ -1,5 +1,12 @@ import { EscrowUtils } from '@human-protocol/sdk'; -import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import { + CanActivate, + ExecutionContext, + HttpException, + HttpStatus, + Injectable, +} from '@nestjs/common'; +import { ethers } from 'ethers'; import { HEADER_SIGNATURE_KEY } from '../constants'; import { Role } from '../enums/role'; @@ -17,6 +24,9 @@ export class SignatureAuthGuard implements CanActivate { const request = context.switchToHttp().getRequest(); const data = request.body; + if (!data.chain_id || !ethers.isAddress(data.escrow_address)) { + throw new HttpException('Invalid payload', HttpStatus.BAD_REQUEST); + } const signature = request.headers[HEADER_SIGNATURE_KEY]; const oracleAdresses: string[] = []; try { diff --git a/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.spec.ts b/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.spec.ts index 63134a0aa8..b9d07aed22 100644 --- a/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.spec.ts +++ b/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.spec.ts @@ -201,6 +201,38 @@ describe('SignatureAuthGuard', () => { expect(thrownError.status).toBe(HttpStatus.UNAUTHORIZED); }); + it('should throw bad request when escrow address is not valid', async () => { + const guard = new SignatureAuthGuard([AuthSignatureRole.JOB_LAUNCHER]); + + mockedEscrowUtils.getEscrow.mockResolvedValueOnce(null); + + body.escrow_address = body.escrow_address.slice(0, -1); + + const { privateKey } = generateEthWallet(); + const signature = await signMessage(body, privateKey); + + const request = { + headers: { + 'human-signature': signature, + }, + body, + }; + executionContextMock.__getRequest.mockReturnValueOnce(request); + + let thrownError: unknown; + try { + await guard.canActivate( + executionContextMock as unknown as ExecutionContext, + ); + } catch (error) { + thrownError = error; + } + expect(thrownError).toBeInstanceOf(HttpException); + const httpError = thrownError as HttpException; + expect(httpError.message).toBe('Invalid payload'); + expect(httpError.getStatus()).toBe(HttpStatus.BAD_REQUEST); + }); + it('should throw bad request when escrow data is missing', async () => { const guard = new SignatureAuthGuard([AuthSignatureRole.JOB_LAUNCHER]); diff --git a/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.ts b/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.ts index 5d814bca3e..5d615d65c9 100644 --- a/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.ts +++ b/packages/apps/reputation-oracle/server/src/common/guards/signature.auth.ts @@ -6,6 +6,7 @@ import { HttpStatus, Injectable, } from '@nestjs/common'; +import { ethers } from 'ethers'; import { HEADER_SIGNATURE_KEY } from '@/common/constants'; import { verifySignature } from '@/utils/web3'; @@ -38,7 +39,7 @@ export class SignatureAuthGuard implements CanActivate { const request = context.switchToHttp().getRequest(); const data = request.body as SignedRequestData; - if (!data.chain_id || !data.escrow_address) { + if (!data.chain_id || !ethers.isAddress(data.escrow_address)) { throw new HttpException('Invalid payload', HttpStatus.BAD_REQUEST); } From 1b7cfab05cc5d84fa3a3b15f2479b39a52f7d2bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Thu, 8 Jan 2026 15:18:17 +0100 Subject: [PATCH 17/21] [Reputation Oracle] fix on-chain staked balance calculation (#3735) --- .../src/modules/staking/staking.service.spec.ts | 13 +++---------- .../server/src/modules/staking/staking.service.ts | 4 +--- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts index bac6576a7b..7657803a1a 100644 --- a/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.spec.ts @@ -169,22 +169,17 @@ describe('StakingService', () => { }); describe('getOnChainStakedBalance', () => { - it('returns total staked and locked balance', async () => { + it('returns total staked balance', async () => { const address = faker.finance.ethereumAddress(); const stakedAmount = ethers.toBigInt( faker.number.int({ min: 500, max: 1000000 }), ); - const lockedAmount = ethers.toBigInt( - faker.number.int({ min: 500, max: 999999 }), - ); const mockProvider = {}; mockWeb3Service.getSigner.mockReturnValueOnce({ provider: mockProvider, } as WalletWithProvider); - const getStakerInfoMock = jest - .fn() - .mockResolvedValue({ stakedAmount, lockedAmount }); + const getStakerInfoMock = jest.fn().mockResolvedValue({ stakedAmount }); mockedStakingClient.build.mockResolvedValueOnce({ getStakerInfo: getStakerInfoMock, } as unknown as StakingClient); @@ -193,9 +188,7 @@ describe('StakingService', () => { expect(mockedStakingClient.build).toHaveBeenCalledWith(mockProvider); expect(getStakerInfoMock).toHaveBeenCalledWith(address); - expect(result).toBe( - Number(ethers.formatEther(stakedAmount + lockedAmount)), - ); + expect(result).toBe(Number(ethers.formatEther(stakedAmount))); }); }); diff --git a/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts index b99412ddb0..4103b91e91 100644 --- a/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/staking/staking.service.ts @@ -53,9 +53,7 @@ export class StakingService { const stakingClient = await StakingClient.build(provider); const stakerInfo = await stakingClient.getStakerInfo(address); - const total = - (stakerInfo.stakedAmount ?? 0n) + (stakerInfo.lockedAmount ?? 0n); - return Number(ethers.formatEther(total)); + return Number(ethers.formatEther(stakerInfo.stakedAmount ?? 0n)); } async getStakeSummary(userId: number): Promise { From 1263e6e770a756f01554bea8f0c8001ce0dc4f71 Mon Sep 17 00:00:00 2001 From: Dmitry Nechay Date: Mon, 12 Jan 2026 14:00:02 +0300 Subject: [PATCH 18/21] [Staking] fix: dashboard client (#3738) --- .../apps/staking/src/services/dashboard.ts | 4 +- packages/apps/staking/src/utils/api.ts | 28 ------------ .../apps/staking/src/utils/case-converter.ts | 44 ------------------- 3 files changed, 2 insertions(+), 74 deletions(-) delete mode 100644 packages/apps/staking/src/utils/case-converter.ts diff --git a/packages/apps/staking/src/services/dashboard.ts b/packages/apps/staking/src/services/dashboard.ts index 5900576d32..b1df0d863b 100644 --- a/packages/apps/staking/src/services/dashboard.ts +++ b/packages/apps/staking/src/services/dashboard.ts @@ -3,10 +3,10 @@ import api from '../utils/api'; export const getKVStoreData = async ( address: string, - chainId: number + chainId: number, ): Promise => { const response = await api.get(`details/kvstore/${address}`, { - params: { chain_id: chainId }, + params: { chainId }, }); // Validate if response is IKVStore[] diff --git a/packages/apps/staking/src/utils/api.ts b/packages/apps/staking/src/utils/api.ts index ac5315fb3b..a6a6037bad 100644 --- a/packages/apps/staking/src/utils/api.ts +++ b/packages/apps/staking/src/utils/api.ts @@ -1,35 +1,7 @@ import axios from 'axios'; -import { CaseConverter } from './case-converter'; const axiosInstance = axios.create({ baseURL: import.meta.env.VITE_APP_DASHBOARD_API_URL, }); -axiosInstance.interceptors.request.use( - (config) => { - if (config.data) { - config.data = CaseConverter.transformToSnakeCase(config.data); - } - - if (config.params) { - config.params = CaseConverter.transformToSnakeCase(config.params); - } - - return config; - }, - (error) => Promise.reject(error) -); - -axiosInstance.interceptors.response.use( - (response) => { - if (response.data) { - response.data = CaseConverter.transformToCamelCase(response.data); - } - return response; - }, - (error) => { - return Promise.reject(error); - } -); - export default axiosInstance; diff --git a/packages/apps/staking/src/utils/case-converter.ts b/packages/apps/staking/src/utils/case-converter.ts deleted file mode 100644 index b2ed3545e6..0000000000 --- a/packages/apps/staking/src/utils/case-converter.ts +++ /dev/null @@ -1,44 +0,0 @@ -export class CaseConverter { - static transformToCamelCase(obj: any): any { - if (Array.isArray(obj)) { - return obj.map((item) => CaseConverter.transformToCamelCase(item)); - } else if (typeof obj === 'object' && obj !== null) { - return Object.keys(obj).reduce( - (acc: Record, key: string) => { - const camelCaseKey = key.replace(/_([a-z])/g, (g) => - g[1].toUpperCase() - ); - acc[camelCaseKey] = CaseConverter.transformToCamelCase(obj[key]); - return acc; - }, - {} - ); - } else { - return obj; - } - } - - static transformToSnakeCase(obj: any): any { - if (Array.isArray(obj)) { - return obj.map((item) => CaseConverter.transformToSnakeCase(item)); - } else if (typeof obj === 'object' && obj !== null) { - return Object.keys(obj).reduce( - (acc: Record, key: string) => { - const snakeCaseKey = key.replace(/([A-Z])/g, '_$1').toLowerCase(); - acc[snakeCaseKey] = CaseConverter.transformToSnakeCase(obj[key]); - return acc; - }, - {} - ); - } else { - return obj; - } - } - - static convertSnakeToHumanReadable(string: string): string { - return string - .split('_') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) - .join(' '); - } -} From 58a44143cbafb03daebf1ca495d8a3ec86af4e5d Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:33:41 +0100 Subject: [PATCH 19/21] Remove temporal fix for cancelation refunds (#3731) --- .../src/modules/job/job.service.spec.ts | 61 ++----------- .../server/src/modules/job/job.service.ts | 89 +++---------------- 2 files changed, 15 insertions(+), 135 deletions(-) diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts index d9e1daf9c7..42f7b763b0 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.spec.ts @@ -1660,62 +1660,17 @@ describe('JobService', () => { expect(mockJobRepository.updateOne).toHaveBeenCalledWith(jobEntity); }); - it('should not create a refund and set status to CANCELED when no refund is found', async () => { + it('should throw ConflictError when no refund is found', async () => { const jobEntity = createJobEntity(); mockPaymentService.getJobPayments.mockResolvedValueOnce([]); mockedEscrowUtils.getCancellationRefund.mockResolvedValueOnce( null as any, ); - jest - .spyOn(jobService as any, 'getRefundAmount') - .mockResolvedValueOnce(0n); - - mockJobRepository.updateOne.mockResolvedValueOnce(jobEntity); - - await jobService.cancelJob(jobEntity); - - expect(mockPaymentService.getJobPayments).toHaveBeenCalledWith( - jobEntity.id, - PaymentType.SLASH, - ); - expect(EscrowUtils.getCancellationRefund).toHaveBeenCalledWith( - jobEntity.chainId, - jobEntity.escrowAddress, - ); - expect(mockPaymentService.createRefundPayment).not.toHaveBeenCalled(); - expect(jobEntity.status).toBe(JobStatus.CANCELED); - expect(mockJobRepository.updateOne).toHaveBeenCalledWith(jobEntity); - }); - - it('should create a refund when on-chain refund amount is greater than 0', async () => { - const jobEntity = createJobEntity(); - const tokenDecimals = (TOKEN_ADDRESSES[jobEntity.chainId as ChainId] ?? - {})[jobEntity.token as EscrowFundToken]?.decimals; - - mockPaymentService.getJobPayments.mockResolvedValueOnce([]); - mockedEscrowUtils.getCancellationRefund.mockResolvedValueOnce( - null as any, + await expect(jobService.cancelJob(jobEntity)).rejects.toThrow( + new ConflictError(ErrorJob.NoRefundFound), ); - const refundAmount = faker.number.float({ - min: 1, - max: 10, - fractionDigits: tokenDecimals, - }); - - // Mock on-chain refund lookup to return a positive amount - jest - .spyOn(jobService as any, 'getRefundAmount') - .mockResolvedValueOnce( - ethers.parseUnits(refundAmount.toString(), tokenDecimals), - ); - - mockPaymentService.createRefundPayment.mockResolvedValueOnce(undefined); - mockJobRepository.updateOne.mockResolvedValueOnce(jobEntity); - - await jobService.cancelJob(jobEntity); - expect(mockPaymentService.getJobPayments).toHaveBeenCalledWith( jobEntity.id, PaymentType.SLASH, @@ -1724,14 +1679,8 @@ describe('JobService', () => { jobEntity.chainId, jobEntity.escrowAddress, ); - expect(mockPaymentService.createRefundPayment).toHaveBeenCalledWith({ - refundAmount: refundAmount, - refundCurrency: jobEntity.token, - userId: jobEntity.userId, - jobId: jobEntity.id, - }); - expect(jobEntity.status).toBe(JobStatus.CANCELED); - expect(mockJobRepository.updateOne).toHaveBeenCalledWith(jobEntity); + expect(mockPaymentService.createRefundPayment).not.toHaveBeenCalled(); + expect(mockJobRepository.updateOne).not.toHaveBeenCalled(); }); it('should throw ConflictError if refund.amount is empty', async () => { diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index d1b69abb00..5984349463 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -1,10 +1,8 @@ -import { Escrow, Escrow__factory } from '@human-protocol/core/typechain-types'; import { ChainId, EscrowClient, EscrowStatus, EscrowUtils, - ICancellationRefund, KVStoreKeys, KVStoreUtils, NETWORKS, @@ -863,35 +861,20 @@ export class JobService { PaymentType.SLASH, ); if (!slash?.length) { - let refund: ICancellationRefund | null = null; - try { - refund = await EscrowUtils.getCancellationRefund( - jobEntity.chainId, - jobEntity.escrowAddress!, - ); - } catch { - // Ignore error - } - - let amount = 0n; + const refund = await EscrowUtils.getCancellationRefund( + jobEntity.chainId, + jobEntity.escrowAddress!, + ); - if (!refund) { - //Temp fix - amount = await this.getRefundAmount( - jobEntity.chainId, - jobEntity.escrowAddress!, - token.address, - ); - } else { - if (!refund.amount) { - throw new ConflictError(ErrorJob.NoRefundFound); - } - amount = refund.amount; + if (!refund || !refund.amount) { + throw new ConflictError(ErrorJob.NoRefundFound); } - if (amount > 0n) { + if (refund.amount > 0n) { await this.paymentService.createRefundPayment({ - refundAmount: Number(ethers.formatUnits(amount, token.decimals)), + refundAmount: Number( + ethers.formatUnits(refund.amount, token.decimals), + ), refundCurrency: jobEntity.token, userId: jobEntity.userId, jobId: jobEntity.id, @@ -902,56 +885,4 @@ export class JobService { jobEntity.status = JobStatus.CANCELED; await this.jobRepository.updateOne(jobEntity); } - - public async getRefundAmount( - chainId: ChainId, - escrowAddress: string, - tokenAddress: string, - ): Promise { - const signer = this.web3Service.getSigner(chainId); - const provider = signer.provider!; - const contract: Escrow = Escrow__factory.connect(escrowAddress!, provider); - const fromBlock = 79278120; //This issue started at this block - const toBlock = 'latest'; - const cancelledFilter = contract.filters?.Cancelled?.(); - const cancelledLogs = await contract.queryFilter( - cancelledFilter, - fromBlock, - toBlock, - ); - - for (const log of cancelledLogs) { - const erc20Interface = new ethers.Interface([ - 'event Transfer(address indexed from, address indexed to, uint256 value)', - ]); - - const transferTopic = erc20Interface.getEvent('Transfer')!.topicHash; - const receipt = await provider.getTransactionReceipt(log.transactionHash); - - const transferLogs = receipt!.logs.filter( - (l) => - l.address.toLowerCase() === tokenAddress.toLowerCase() && - l.topics[0] === transferTopic, - ); - for (const tlog of transferLogs) { - const decoded = erc20Interface.decodeEventLog( - 'Transfer', - tlog.data, - tlog.topics, - ); - - const from = decoded.from as string; - const to = decoded.to as string; - const value = decoded.value as bigint; - if ( - from.toLowerCase() === escrowAddress.toLowerCase() && - to.toLowerCase() === (await signer.getAddress()).toLowerCase() - ) { - return value; - } - } - } - - return 0n; - } } From 4bebfec434985e1eee765f5cd8d569673a29c0e0 Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:39:05 +0100 Subject: [PATCH 20/21] Use Mkdocs for sdk documents (#3721) --- .github/workflows/cd-gitbook-sdk-docs.yaml | 29 - .gitignore | 4 + docs/README.md | 42 + docs/index.html | 218 +++ docs/mkdocs-python.yaml | 98 + docs/mkdocs-ts.yaml | 89 + docs/overrides/assets/css/custom.css | 279 +++ docs/overrides/assets/img/logo.svg | 3 + docs/overrides/assets/img/python-logo.webp | Bin 0 -> 9414 bytes docs/overrides/assets/img/ts-logo.png | Bin 0 -> 21739 bytes docs/overrides/partials/header.html | 171 ++ docs/overrides/partials/logo.html | 10 + docs/requirements.txt | 6 + docs/sdk/README.md | 38 - docs/sdk/SUMMARY.md | 61 - docs/sdk/changelog.md | 36 - .../human_protocol_sdk.agreement.bootstrap.md | 41 - .../python/human_protocol_sdk.agreement.md | 105 -- .../human_protocol_sdk.agreement.measures.md | 226 --- .../human_protocol_sdk.agreement.utils.md | 226 --- .../python/human_protocol_sdk.constants.md | 105 -- .../python/human_protocol_sdk.decorators.md | 9 - ...uman_protocol_sdk.encryption.encryption.md | 193 -- ...rotocol_sdk.encryption.encryption_utils.md | 236 --- .../python/human_protocol_sdk.encryption.md | 22 - ...human_protocol_sdk.escrow.escrow_client.md | 616 ------- .../human_protocol_sdk.escrow.escrow_utils.md | 231 --- docs/sdk/python/human_protocol_sdk.escrow.md | 63 - docs/sdk/python/human_protocol_sdk.filter.md | 174 -- ...man_protocol_sdk.kvstore.kvstore_client.md | 100 -- ...uman_protocol_sdk.kvstore.kvstore_utils.md | 135 -- docs/sdk/python/human_protocol_sdk.kvstore.md | 26 - .../human_protocol_sdk.legacy_encryption.md | 162 -- docs/sdk/python/human_protocol_sdk.md | 224 --- .../sdk/python/human_protocol_sdk.operator.md | 22 - ...an_protocol_sdk.operator.operator_utils.md | 188 -- docs/sdk/python/human_protocol_sdk.staking.md | 28 - ...man_protocol_sdk.staking.staking_client.md | 106 -- ...uman_protocol_sdk.staking.staking_utils.md | 49 - .../python/human_protocol_sdk.statistics.md | 38 - ...otocol_sdk.statistics.statistics_client.md | 349 ---- docs/sdk/python/human_protocol_sdk.storage.md | 22 - ...man_protocol_sdk.storage.storage_client.md | 246 --- ...uman_protocol_sdk.storage.storage_utils.md | 30 - .../python/human_protocol_sdk.transaction.md | 18 - ...tocol_sdk.transaction.transaction_utils.md | 105 -- docs/sdk/python/human_protocol_sdk.utils.md | 150 -- docs/sdk/python/human_protocol_sdk.worker.md | 13 - .../human_protocol_sdk.worker.worker_utils.md | 52 - docs/sdk/python/index.md | 83 - docs/sdk/typescript/README.md | 37 - docs/sdk/typescript/base/README.md | 11 - .../base/classes/BaseEthersClient.md | 63 - docs/sdk/typescript/encryption/README.md | 12 - .../encryption/classes/Encryption.md | 257 --- .../encryption/classes/EncryptionUtils.md | 283 --- docs/sdk/typescript/enums/README.md | 13 - .../typescript/enums/enumerations/ChainId.md | 73 - .../enums/enumerations/OperatorCategory.md | 25 - .../enums/enumerations/OrderDirection.md | 25 - docs/sdk/typescript/escrow/README.md | 12 - .../typescript/escrow/classes/EscrowClient.md | 1572 ----------------- .../typescript/escrow/classes/EscrowUtils.md | 538 ------ docs/sdk/typescript/graphql/types/README.md | 29 - .../types/interfaces/IOperatorSubgraph.md | 141 -- .../interfaces/IReputationNetworkSubgraph.md | 45 - .../type-aliases/CancellationRefundData.md | 67 - .../graphql/types/type-aliases/EscrowData.md | 203 --- .../type-aliases/EscrowStatisticsData.md | 91 - .../types/type-aliases/EventDayData.md | 155 -- .../types/type-aliases/HMTHolderData.md | 27 - .../types/type-aliases/HMTStatisticsData.md | 59 - .../type-aliases/InternalTransactionData.md | 75 - .../graphql/types/type-aliases/KVStoreData.md | 59 - .../graphql/types/type-aliases/PayoutData.md | 51 - .../type-aliases/RewardAddedEventData.md | 43 - .../graphql/types/type-aliases/StakerData.md | 75 - .../graphql/types/type-aliases/StatusEvent.md | 35 - .../types/type-aliases/TransactionData.md | 99 -- .../graphql/types/type-aliases/WorkerData.md | 43 - docs/sdk/typescript/interfaces/README.md | 47 - .../interfaces/ICancellationRefund.md | 65 - .../interfaces/ICancellationRefundFilter.md | 89 - .../interfaces/interfaces/IDailyEscrow.md | 57 - .../interfaces/interfaces/IDailyHMT.md | 49 - .../interfaces/interfaces/IDailyPayment.md | 41 - .../interfaces/interfaces/IDailyWorker.md | 25 - .../interfaces/interfaces/IEscrow.md | 209 --- .../interfaces/interfaces/IEscrowConfig.md | 73 - .../interfaces/IEscrowStatistics.md | 25 - .../interfaces/interfaces/IEscrowWithdraw.md | 33 - .../interfaces/interfaces/IEscrowsFilter.md | 121 -- .../interfaces/interfaces/IHMTHolder.md | 25 - .../interfaces/IHMTHoldersParams.md | 57 - .../interfaces/interfaces/IHMTStatistics.md | 33 - .../interfaces/interfaces/IKVStore.md | 25 - .../interfaces/interfaces/IKeyPair.md | 41 - .../interfaces/interfaces/IOperator.md | 177 -- .../interfaces/interfaces/IOperatorsFilter.md | 81 - .../interfaces/interfaces/IPagination.md | 46 - .../interfaces/IPaymentStatistics.md | 17 - .../interfaces/interfaces/IPayout.md | 49 - .../interfaces/interfaces/IPayoutFilter.md | 89 - .../interfaces/IReputationNetwork.md | 33 - .../interfaces/interfaces/IReward.md | 25 - .../interfaces/interfaces/IStaker.md | 65 - .../interfaces/interfaces/IStakersFilter.md | 129 -- .../interfaces/IStatisticsFilter.md | 65 - .../interfaces/interfaces/IStatusEvent.md | 41 - .../interfaces/IStatusEventFilter.md | 89 - .../interfaces/interfaces/ITransaction.md | 97 - .../interfaces/ITransactionsFilter.md | 129 -- .../interfaces/interfaces/IWorker.md | 41 - .../interfaces/IWorkerStatistics.md | 17 - .../interfaces/interfaces/IWorkersFilter.md | 73 - .../interfaces/InternalTransaction.md | 65 - .../interfaces/interfaces/StakerInfo.md | 41 - .../interfaces/interfaces/SubgraphOptions.md | 42 - docs/sdk/typescript/kvstore/README.md | 12 - .../kvstore/classes/KVStoreClient.md | 378 ---- .../kvstore/classes/KVStoreUtils.md | 270 --- docs/sdk/typescript/modules.md | 21 - docs/sdk/typescript/operator/README.md | 11 - .../operator/classes/OperatorUtils.md | 198 --- docs/sdk/typescript/staking/README.md | 12 - .../staking/classes/StakingClient.md | 482 ----- .../staking/classes/StakingUtils.md | 87 - docs/sdk/typescript/statistics/README.md | 11 - .../statistics/classes/StatisticsClient.md | 474 ----- docs/sdk/typescript/storage/README.md | 11 - .../storage/classes/StorageClient.md | 305 ---- docs/sdk/typescript/transaction/README.md | 11 - .../transaction/classes/TransactionUtils.md | 184 -- docs/sdk/typescript/types/README.md | 19 - .../types/enumerations/EscrowStatus.md | 81 - .../types/type-aliases/NetworkData.md | 123 -- .../types/type-aliases/StorageCredentials.md | 37 - .../types/type-aliases/StorageParams.md | 55 - .../type-aliases/TransactionLikeWithNonce.md | 17 - .../types/type-aliases/UploadFile.md | 43 - .../sdk/python/human-protocol-sdk/Makefile | 9 - .../python/human-protocol-sdk/docs/Makefile | 20 - .../python/human-protocol-sdk/docs/conf.py | 54 - .../python/human-protocol-sdk/docs/core.md | 19 + .../human-protocol-sdk/docs/encryption.md | 1 + .../docs/encryption_utils.md | 1 + .../human-protocol-sdk/docs/escrow_client.md | 1 + .../human-protocol-sdk/docs/escrow_utils.md | 1 + ...human_protocol_sdk.agreement.bootstrap.rst | 7 - .../human_protocol_sdk.agreement.measures.rst | 7 - .../docs/human_protocol_sdk.agreement.rst | 17 - .../human_protocol_sdk.agreement.utils.rst | 7 - .../docs/human_protocol_sdk.constants.rst | 7 - .../docs/human_protocol_sdk.decorators.rst | 7 - ...man_protocol_sdk.encryption.encryption.rst | 7 - ...otocol_sdk.encryption.encryption_utils.rst | 7 - .../docs/human_protocol_sdk.encryption.rst | 16 - ...uman_protocol_sdk.escrow.escrow_client.rst | 7 - ...human_protocol_sdk.escrow.escrow_utils.rst | 7 - .../docs/human_protocol_sdk.escrow.rst | 16 - .../docs/human_protocol_sdk.filter.rst | 7 - ...an_protocol_sdk.kvstore.kvstore_client.rst | 7 - ...man_protocol_sdk.kvstore.kvstore_utils.rst | 7 - .../docs/human_protocol_sdk.kvstore.rst | 16 - .../human_protocol_sdk.legacy_encryption.rst | 7 - ...n_protocol_sdk.operator.operator_utils.rst | 7 - .../docs/human_protocol_sdk.operator.rst | 15 - .../docs/human_protocol_sdk.rst | 35 - .../docs/human_protocol_sdk.staking.rst | 16 - ...an_protocol_sdk.staking.staking_client.rst | 7 - ...man_protocol_sdk.staking.staking_utils.rst | 7 - .../docs/human_protocol_sdk.statistics.rst | 15 - ...tocol_sdk.statistics.statistics_client.rst | 7 - .../docs/human_protocol_sdk.storage.rst | 16 - ...an_protocol_sdk.storage.storage_client.rst | 7 - ...man_protocol_sdk.storage.storage_utils.rst | 7 - .../docs/human_protocol_sdk.transaction.rst | 15 - ...ocol_sdk.transaction.transaction_utils.rst | 7 - .../docs/human_protocol_sdk.utils.rst | 7 - .../docs/human_protocol_sdk.worker.rst | 15 - ...human_protocol_sdk.worker.worker_utils.rst | 7 - .../python/human-protocol-sdk/docs/index.md | 215 +++ .../python/human-protocol-sdk/docs/index.rst | 28 - .../human-protocol-sdk/docs/kvstore_client.md | 1 + .../human-protocol-sdk/docs/kvstore_utils.md | 1 + .../docs/legacy_encryption.md | 1 + .../python/human-protocol-sdk/docs/make.bat | 35 - .../human-protocol-sdk/docs/operator_utils.md | 1 + .../human-protocol-sdk/docs/staking_client.md | 1 + .../human-protocol-sdk/docs/staking_utils.md | 1 + .../docs/statistics_utils.md | 1 + .../docs/transaction_utils.md | 1 + .../human-protocol-sdk/docs/worker_utils.md | 7 + .../human_protocol_sdk/agreement/__init__.py | 85 - .../human_protocol_sdk/agreement/bootstrap.py | 142 -- .../human_protocol_sdk/agreement/measures.py | 377 ---- .../human_protocol_sdk/agreement/utils.py | 417 ----- .../human_protocol_sdk/constants.py | 69 +- .../human_protocol_sdk/decorators.py | 50 +- .../encryption/encryption.py | 250 +-- .../encryption/encryption_utils.py | 294 +-- .../escrow/escrow_client.py | 1285 +++++--------- .../human_protocol_sdk/escrow/escrow_utils.py | 357 ++-- .../human_protocol_sdk/filter.py | 236 ++- .../kvstore/kvstore_client.py | 262 ++- .../kvstore/kvstore_utils.py | 233 ++- .../human_protocol_sdk/legacy_encryption.py | 305 ++-- .../operator/operator_utils.py | 295 ++-- .../staking/staking_client.py | 428 ++--- .../staking/staking_utils.py | 113 +- .../statistics/statistics_client.py | 666 ------- .../statistics/statistics_utils.py | 712 ++++++++ .../transaction/transaction_utils.py | 197 ++- .../human_protocol_sdk/utils.py | 303 +++- .../human_protocol_sdk/worker/worker_utils.py | 117 +- .../typescript/human-protocol-sdk/.gitignore | 4 +- .../human-protocol-sdk/docs/index.md | 294 +++ .../human-protocol-sdk/package.json | 26 +- .../scripts/postprocess-docs.ts | 457 +++++ .../typescript/human-protocol-sdk/src/base.ts | 9 +- .../human-protocol-sdk/src/encryption.ts | 272 +-- .../human-protocol-sdk/src/escrow.ts | 1203 +++++-------- .../human-protocol-sdk/src/index.ts | 7 +- .../human-protocol-sdk/src/kvstore.ts | 301 ++-- .../human-protocol-sdk/src/operator.ts | 89 +- .../human-protocol-sdk/src/staking.ts | 269 +-- .../human-protocol-sdk/src/statistics.ts | 271 ++- .../human-protocol-sdk/src/transaction.ts | 51 +- .../human-protocol-sdk/src/utils.ts | 48 +- .../human-protocol-sdk/src/worker.ts | 49 +- .../human-protocol-sdk/tsconfig.eslint.json | 2 +- .../human-protocol-sdk/typedoc.json | 46 + yarn.lock | 97 +- 233 files changed, 6207 insertions(+), 20189 deletions(-) delete mode 100644 .github/workflows/cd-gitbook-sdk-docs.yaml create mode 100644 docs/README.md create mode 100644 docs/index.html create mode 100644 docs/mkdocs-python.yaml create mode 100644 docs/mkdocs-ts.yaml create mode 100644 docs/overrides/assets/css/custom.css create mode 100644 docs/overrides/assets/img/logo.svg create mode 100644 docs/overrides/assets/img/python-logo.webp create mode 100644 docs/overrides/assets/img/ts-logo.png create mode 100644 docs/overrides/partials/header.html create mode 100644 docs/overrides/partials/logo.html create mode 100644 docs/requirements.txt delete mode 100644 docs/sdk/README.md delete mode 100644 docs/sdk/SUMMARY.md delete mode 100644 docs/sdk/changelog.md delete mode 100644 docs/sdk/python/human_protocol_sdk.agreement.bootstrap.md delete mode 100644 docs/sdk/python/human_protocol_sdk.agreement.md delete mode 100644 docs/sdk/python/human_protocol_sdk.agreement.measures.md delete mode 100644 docs/sdk/python/human_protocol_sdk.agreement.utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.constants.md delete mode 100644 docs/sdk/python/human_protocol_sdk.decorators.md delete mode 100644 docs/sdk/python/human_protocol_sdk.encryption.encryption.md delete mode 100644 docs/sdk/python/human_protocol_sdk.encryption.encryption_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.encryption.md delete mode 100644 docs/sdk/python/human_protocol_sdk.escrow.escrow_client.md delete mode 100644 docs/sdk/python/human_protocol_sdk.escrow.escrow_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.escrow.md delete mode 100644 docs/sdk/python/human_protocol_sdk.filter.md delete mode 100644 docs/sdk/python/human_protocol_sdk.kvstore.kvstore_client.md delete mode 100644 docs/sdk/python/human_protocol_sdk.kvstore.kvstore_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.kvstore.md delete mode 100644 docs/sdk/python/human_protocol_sdk.legacy_encryption.md delete mode 100644 docs/sdk/python/human_protocol_sdk.md delete mode 100644 docs/sdk/python/human_protocol_sdk.operator.md delete mode 100644 docs/sdk/python/human_protocol_sdk.operator.operator_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.staking.md delete mode 100644 docs/sdk/python/human_protocol_sdk.staking.staking_client.md delete mode 100644 docs/sdk/python/human_protocol_sdk.staking.staking_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.statistics.md delete mode 100644 docs/sdk/python/human_protocol_sdk.statistics.statistics_client.md delete mode 100644 docs/sdk/python/human_protocol_sdk.storage.md delete mode 100644 docs/sdk/python/human_protocol_sdk.storage.storage_client.md delete mode 100644 docs/sdk/python/human_protocol_sdk.storage.storage_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.transaction.md delete mode 100644 docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.utils.md delete mode 100644 docs/sdk/python/human_protocol_sdk.worker.md delete mode 100644 docs/sdk/python/human_protocol_sdk.worker.worker_utils.md delete mode 100644 docs/sdk/python/index.md delete mode 100644 docs/sdk/typescript/README.md delete mode 100644 docs/sdk/typescript/base/README.md delete mode 100644 docs/sdk/typescript/base/classes/BaseEthersClient.md delete mode 100644 docs/sdk/typescript/encryption/README.md delete mode 100644 docs/sdk/typescript/encryption/classes/Encryption.md delete mode 100644 docs/sdk/typescript/encryption/classes/EncryptionUtils.md delete mode 100644 docs/sdk/typescript/enums/README.md delete mode 100644 docs/sdk/typescript/enums/enumerations/ChainId.md delete mode 100644 docs/sdk/typescript/enums/enumerations/OperatorCategory.md delete mode 100644 docs/sdk/typescript/enums/enumerations/OrderDirection.md delete mode 100644 docs/sdk/typescript/escrow/README.md delete mode 100644 docs/sdk/typescript/escrow/classes/EscrowClient.md delete mode 100644 docs/sdk/typescript/escrow/classes/EscrowUtils.md delete mode 100644 docs/sdk/typescript/graphql/types/README.md delete mode 100644 docs/sdk/typescript/graphql/types/interfaces/IOperatorSubgraph.md delete mode 100644 docs/sdk/typescript/graphql/types/interfaces/IReputationNetworkSubgraph.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/CancellationRefundData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/InternalTransactionData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/StakerData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/TransactionData.md delete mode 100644 docs/sdk/typescript/graphql/types/type-aliases/WorkerData.md delete mode 100644 docs/sdk/typescript/interfaces/README.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/ICancellationRefund.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/ICancellationRefundFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IDailyEscrow.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IDailyHMT.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IDailyPayment.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IDailyWorker.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrow.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrowStatistics.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrowWithdraw.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IHMTHolder.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IHMTStatistics.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IKVStore.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IKeyPair.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IOperator.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IOperatorsFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IPagination.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IPaymentStatistics.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IPayout.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IReward.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IStaker.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IStakersFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IStatusEvent.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IStatusEventFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/ITransaction.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IWorker.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IWorkerStatistics.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/IWorkersFilter.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/StakerInfo.md delete mode 100644 docs/sdk/typescript/interfaces/interfaces/SubgraphOptions.md delete mode 100644 docs/sdk/typescript/kvstore/README.md delete mode 100644 docs/sdk/typescript/kvstore/classes/KVStoreClient.md delete mode 100644 docs/sdk/typescript/kvstore/classes/KVStoreUtils.md delete mode 100644 docs/sdk/typescript/modules.md delete mode 100644 docs/sdk/typescript/operator/README.md delete mode 100644 docs/sdk/typescript/operator/classes/OperatorUtils.md delete mode 100644 docs/sdk/typescript/staking/README.md delete mode 100644 docs/sdk/typescript/staking/classes/StakingClient.md delete mode 100644 docs/sdk/typescript/staking/classes/StakingUtils.md delete mode 100644 docs/sdk/typescript/statistics/README.md delete mode 100644 docs/sdk/typescript/statistics/classes/StatisticsClient.md delete mode 100644 docs/sdk/typescript/storage/README.md delete mode 100644 docs/sdk/typescript/storage/classes/StorageClient.md delete mode 100644 docs/sdk/typescript/transaction/README.md delete mode 100644 docs/sdk/typescript/transaction/classes/TransactionUtils.md delete mode 100644 docs/sdk/typescript/types/README.md delete mode 100644 docs/sdk/typescript/types/enumerations/EscrowStatus.md delete mode 100644 docs/sdk/typescript/types/type-aliases/NetworkData.md delete mode 100644 docs/sdk/typescript/types/type-aliases/StorageCredentials.md delete mode 100644 docs/sdk/typescript/types/type-aliases/StorageParams.md delete mode 100644 docs/sdk/typescript/types/type-aliases/TransactionLikeWithNonce.md delete mode 100644 docs/sdk/typescript/types/type-aliases/UploadFile.md delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/Makefile delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/conf.py create mode 100644 packages/sdk/python/human-protocol-sdk/docs/core.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/encryption.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/encryption_utils.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/escrow_client.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/escrow_utils.md delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.bootstrap.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.measures.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.constants.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.decorators.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_client.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.filter.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_client.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.legacy_encryption.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.operator_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_client.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.statistics_client.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_client.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.transaction_utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.utils.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.rst delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.worker_utils.rst create mode 100644 packages/sdk/python/human-protocol-sdk/docs/index.md delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/index.rst create mode 100644 packages/sdk/python/human-protocol-sdk/docs/kvstore_client.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/kvstore_utils.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/legacy_encryption.md delete mode 100644 packages/sdk/python/human-protocol-sdk/docs/make.bat create mode 100644 packages/sdk/python/human-protocol-sdk/docs/operator_utils.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/staking_client.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/staking_utils.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/statistics_utils.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/transaction_utils.md create mode 100644 packages/sdk/python/human-protocol-sdk/docs/worker_utils.md delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/__init__.py delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/bootstrap.py delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/measures.py delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/utils.py delete mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_client.py create mode 100644 packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_utils.py create mode 100644 packages/sdk/typescript/human-protocol-sdk/docs/index.md create mode 100644 packages/sdk/typescript/human-protocol-sdk/scripts/postprocess-docs.ts create mode 100644 packages/sdk/typescript/human-protocol-sdk/typedoc.json diff --git a/.github/workflows/cd-gitbook-sdk-docs.yaml b/.github/workflows/cd-gitbook-sdk-docs.yaml deleted file mode 100644 index 574253955c..0000000000 --- a/.github/workflows/cd-gitbook-sdk-docs.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Publish SDK Docs to GitBook - -on: - push: - tags: - - "js/sdk@*" - -permissions: - contents: read - -jobs: - publish-docs: - name: Sync docs to GitBook - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 - with: - node-version-file: .nvmrc - - name: Publish docs - env: - GITBOOK_API_TOKEN: ${{ secrets.GITBOOK_API_TOKEN }} - GITBOOK_ORG_ID: ${{ secrets.GITBOOK_ORG_ID }} - PARENT_SPACE_ID: ${{ secrets.GITBOOK_PARENT_SPACE_ID }} - GITBOOK_SITE_ID: ${{ secrets.GITBOOK_SITE_ID }} - GIT_REF: ${{ github.ref }} - SPACE_VISIBILITY: ${{ vars.GITBOOK_SPACE_VISIBILITY }} - MAKE_DEFAULT: ${{ vars.GITBOOK_MAKE_DEFAULT }} - run: node scripts/gitbook-sync-sdk.mjs diff --git a/.gitignore b/.gitignore index 6c925760ab..afefc0200f 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,7 @@ cache # Ignore developer-only local files .local + + +docs/ts +docs/python \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..875ad8cd70 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,42 @@ +# SDK Docs workflow + +## Prerequisites +- `pip install -r docs/requirements.txt` +- `yarn install` +- `yarn build:libs` + +## Local preview +- TypeScript docs: `mkdocs serve -f docs/mkdocs-ts.yaml` +- Python docs: `mkdocs serve -f docs/mkdocs-python.yaml` + +## Deploying a new version (mike) +- TypeScript: + `yarn workspace @human-protocol/sdk build:doc` + `mike deploy -F ./docs/mkdocs-ts.yaml --deploy-prefix docs/ts [VERSION]` + `mike set-default -F ./docs/mkdocs-ts.yaml --deploy-prefix docs/ts [VERSION]` +- Python: + `mike deploy -F ./docs/mkdocs-python.yaml --deploy-prefix docs/python [VERSION]` + `mike set-default -F ./docs/mkdocs-python.yaml --deploy-prefix docs/python [VERSION]` + +## Deleting a deployed version +- TypeScript: `mike delete -F ./docs/mkdocs-ts.yaml --deploy-prefix docs/ts [VERSION]` +- Python: `mike delete -F ./docs/mkdocs-python.yaml --deploy-prefix docs/python [VERSION]` + +## Landing page (docs/index.html) +- If you edit `docs/index.html`, apply the change both on your working branch and on `gh-pages`. + +NEVER MERGE THE BRANCHES: `gh-pages` only contains docs builds, not the monorepo code. + +## Serving static files +- Serve only `index.html` (SDK docs won’t load): from `docs/`, run + `python -m http.server 8080 --bind 127.0.0.1` +- Serve the full published docs: create a mike deployment, switch to the `gh-pages` branch, go to `docs/`, then run + `python -m http.server 8080 --bind 127.0.0.1` + +## Repository structure (docs) +- `docs/index.html`: Static landing page that links to SDK docs (TS/Python). +- `docs/mkdocs-ts.yaml`: MkDocs config for the TypeScript site (deploys under `docs/ts` via mike). +- `docs/mkdocs-python.yaml`: MkDocs config for the Python site (deploys under `docs/python` via mike). +- `docs/ts/`: TypeScript site output; versioned builds live under `docs/ts/` with per-version assets in `docs/ts//assets/`. +- `docs/python/`: Python site output (if published); versioned builds live under `docs/python/`. +- `docs/overrides/`: Shared MkDocs theme overrides and assets (logo/header partials and images). diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000000..72ae5385ea --- /dev/null +++ b/docs/index.html @@ -0,0 +1,218 @@ + + + + + HUMAN Protocol SDKs + + + + +
+ +

+ HUMAN Protocol SDKs +

+

+ Choose your preferred language SDK to integrate with HUMAN Protocol. + Both SDKs expose the same core concepts, so you can build automation, + dApps, and services in the stack you know best. +

+ +
+ +
+
+ TypeScript Logo +
+
+ TypeScript + Node.js +
+

TypeScript SDK

+

+ Type-safe SDK for web, dApps and backend services. +

+ +
+ + +
+
+ Python Logo +
+
+ Python +
+

Python SDK

+

+ Python SDK for automation, bots, data/ML pipelines, and backend services. +

+ +
+
+
+ + + + diff --git a/docs/mkdocs-python.yaml b/docs/mkdocs-python.yaml new file mode 100644 index 0000000000..5661c3eb87 --- /dev/null +++ b/docs/mkdocs-python.yaml @@ -0,0 +1,98 @@ +site_name: HUMAN Protocol Python SDK Docs +site_url: https://sdk.humanprotocol.org/python/ +repo_name: humanprotocol/human-protocol +repo_url: https://github.com/humanprotocol/human-protocol +docs_dir: ../packages/sdk/python/human-protocol-sdk/docs +site_dir: python +theme: + name: material + custom_dir: overrides + logo: assets/img/logo.svg + favicon: assets/img/logo.svg + palette: + - scheme: default + primary: deep purple + accent: purple + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: deep purple + accent: purple + toggle: + icon: material/brightness-3 + name: Switch to light mode + font: + text: Noto Sans + code: Roboto Mono + features: + - navigation.instant + - navigation.instant.prefetch + - navigation.top + - navigation.tracking + - navigation.path + - navigation.indexes + - navigation.prune + - content.tabs + - content.code.copy + - toc.follow + - announce.dismiss +extra: + language: python + version: + provider: mike + logo_href: https://sdk.humanprotocol.org +markdown_extensions: + - toc: + baselevel: 1 + permalink: true + - admonition + - pymdownx.details + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.magiclink + - attr_list + - md_in_html +plugins: + - search + - mkdocstrings: + handlers: + python: + paths: [../packages/sdk/python/human-protocol-sdk] + options: + docstring_style: google + show_source: false + separate_signature: true + merge_init_into_class: true + heading_level: 2 + - mike + - section-index +nav: + - Overview: index.md + - Encryption: + - Encryption: encryption.md + - Encryption Utils: encryption_utils.md + - LegacyEncryption: legacy_encryption.md + - Escrow: + - EscrowClient: escrow_client.md + - EscrowUtils: escrow_utils.md + - KVStore: + - KVStoreClient: kvstore_client.md + - KVStoreUtils: kvstore_utils.md + - Operator: + - OperatorUtils: operator_utils.md + - Staking: + - StakingClient: staking_client.md + - StakingUtils: staking_utils.md + - Statistics: + - StatisticsUtils: statistics_utils.md + - Transaction: + - TransactionUtils: transaction_utils.md + - Worker: + - WorkerUtils: worker_utils.md + - Core utilities: core.md +extra_css: + - assets/css/custom.css diff --git a/docs/mkdocs-ts.yaml b/docs/mkdocs-ts.yaml new file mode 100644 index 0000000000..f55a4650d5 --- /dev/null +++ b/docs/mkdocs-ts.yaml @@ -0,0 +1,89 @@ +site_name: HUMAN Protocol TypeScript SDK Docs +site_url: https://sdk.humanprotocol.org/ts/ +repo_name: humanprotocol/human-protocol +repo_url: https://github.com/humanprotocol/human-protocol +docs_dir: ../packages/sdk/typescript/human-protocol-sdk/docs +site_dir: ts +theme: + name: material + custom_dir: overrides + logo: assets/img/logo.svg + favicon: assets/img/logo.svg + palette: + - scheme: default + primary: deep purple + accent: purple + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: deep purple + accent: purple + toggle: + icon: material/brightness-3 + name: Switch to light mode + font: + text: Noto Sans + code: Roboto Mono + features: + - navigation.instant + - navigation.instant.prefetch + - navigation.top + - navigation.tracking + - navigation.path + - navigation.indexes + - navigation.prune + - content.tabs + - content.code.copy + - toc.follow + - announce.dismiss +extra: + language: typescript + version: + provider: mike + logo_href: https://sdk.humanprotocol.org +markdown_extensions: + - toc: + baselevel: 1 + permalink: true + - admonition + - pymdownx.details + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.magiclink + - attr_list + - md_in_html + - pymdownx.escapeall: + hardbreak: false + nbsp: false +plugins: + - search + - mike + - section-index +nav: + - Overview: index.md + - Encryption: + - Encryption: classes/Encryption.md + - Encryption Utils: classes/EncryptionUtils.md + - Escrow: + - EscrowClient: classes/EscrowClient.md + - EscrowUtils: classes/EscrowUtils.md + - KVStore: + - KVStoreClient: classes/KVStoreClient.md + - KVStoreUtils: classes/KVStoreUtils.md + - Operator: + - OperatorUtils: classes/OperatorUtils.md + - Staking: + - StakingClient: classes/StakingClient.md + - StakingUtils: classes/StakingUtils.md + - Statistics: + - StatisticsUtils: classes/StatisticsUtils.md + - Transaction: + - TransactionUtils: classes/TransactionUtils.md + - Worker: + - WorkerUtils: classes/WorkerUtils.md +extra_css: + - assets/css/custom.css diff --git a/docs/overrides/assets/css/custom.css b/docs/overrides/assets/css/custom.css new file mode 100644 index 0000000000..acb3e3d0c7 --- /dev/null +++ b/docs/overrides/assets/css/custom.css @@ -0,0 +1,279 @@ +/* Define brand */ +:root, [data-md-color-scheme="default"] { + --md-default-bg-color: rgb(250, 250, 250); + --md-primary-fg-color: rgb(33, 25, 67); + --md-primary-fg-color--light: rgb(99, 9, 255); + --md-primary-fg-color--dark: rgb(99, 9, 255); + --md-primary-bg-color: rgb(212, 207, 255); + --md-primary-bg-color--light: rgb(212, 207, 255); + --md-accent-fg-color: rgb(212, 207, 255); + --pg-light-border: rgb(99, 9, 255); + --hb-hero-color: rgb(45, 45, 45); + --md-footer-bg-color--dark: var(--md-primary-fg-color); + --md-typeset-a-color: rgb(99, 9, 255); +} +:root, [data-md-color-scheme="slate"] { + --md-default-bg-color: rgb(33, 25, 67); + --md-primary-fg-color: rgb(16, 7, 53); + --md-primary-fg-color--light: rgb(99, 9, 255); + --md-primary-fg-color--dark: rgb(99, 9, 255); + --md-primary-bg-color: rgb(212, 207, 255); + --md-primary-bg-color--light: rgb(212, 207, 255); + --md-accent-fg-color: rgb(99, 9, 255); + --pg-light-border: rgb(47, 47, 47); + --hb-hero-color: rgb(212, 207, 255); + --md-code-bg-color: rgb(22 23 24); + --md-footer-bg-color--dark: var(--md-primary-fg-color); +} + + +.md-typeset .admonition.question, .md-typeset details.question { + border-color: transparent; +} + +.md-typeset .question>.admonition-title:before, .md-typeset .question>summary:before { + background-color: rgb(99, 9, 255); +} + +[data-md-color-scheme="slate"] .md-typeset .question>.admonition-title:before, [data-md-color-scheme="slate"] .md-typeset .question>summary:after { + background-color: rgba(212, 207, 255); +} + +[data-md-color-scheme="default"] .md-typeset .question>.admonition-title:before, [data-md-color-scheme="default"] .md-typeset .question>summary:after { + background-color: rgb(99, 9, 255); +} + +[data-md-color-scheme="slate"] .md-typeset .question>.admonition-title, [data-md-color-scheme="slate"] .md-typeset .question>summary { + background-color: rgb(16, 7, 53); +} + +[data-md-color-scheme="default"] .md-typeset .question>.admonition-title, [data-md-color-scheme="default"] .md-typeset .question>summary { + background-color: rgba(212, 207, 255, 0.25); +} + +[data-md-color-scheme="slate"] .md-typeset .admonition.question:focus-within, [data-md-color-scheme="slate"] .md-typeset details.question:focus-within { + box-shadow: 0 0 0 .2rem rgb(99, 9, 255); +} + +[data-md-color-scheme="default"] .md-typeset .admonition.question:focus-within, [data-md-color-scheme="default"] .md-typeset details.question:focus-within { + box-shadow: 0 0 0 .2rem rgb(212, 207, 255); +} + +/* Hide the logo that appears at the TOP of the left sidebar (drawer) */ +.md-sidebar--primary .md-logo { + display: none !important; +} + +/* Tidy up the title row spacing after removing the logo */ +.md-sidebar--primary .md-nav__title { + padding-top: 0.4rem; + padding-bottom: 0.4rem; +} + +/* Safety: if an inline SVG sneaks in, hide it too */ +.md-sidebar--primary .md-nav__title svg { + display: none !important; +} + +h1, h2, h3, h4, h5, h6 { + font-weight: 700 !important; +} + +/* Language switch: match version switch styling */ +.md-header__langswitch { + position: relative; + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 6px 12px; + border-radius: 999px; + font-weight: 600; + font-size: 0.85rem; + border: 1px solid rgba(255, 255, 255, 0.3); + background: rgba(255, 255, 255, 0.08); + color: #fff; + cursor: pointer; +} + +.md-header__button:hover{ + opacity: 1; +} + +.md-header__langswitch:hover, +.md-header__langswitch:focus-within { + background: #ffffff; /* solid for dark scheme default */ + border-color: #ffffff; /* solid border */ + color: var(--md-primary-fg-color); +} + +/* Light scheme override: use brand color solid instead of rgba */ +[data-md-color-scheme="default"] .md-header__langswitch { + background: rgba(99, 9, 255, 0.08); + color: rgb(212, 207, 255); + border-color: rgba(99, 9, 255); +} + +.md-header__langlabel { + white-space: nowrap; +} + + +.md-header__langmenu { + position: absolute; + top: calc(100% + 14px); + right: 0; + min-width: 170px; + padding: 8px; + border-radius: 10px; + background: var(--md-default-bg-color); + border: 1px solid var(--md-primary-bg-color); + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18); + display: none; + flex-direction: column; + gap: 2px; + z-index: 40; + +} + +.md-header__langswitch:hover .md-header__langmenu, +.md-header__langswitch:focus-within .md-header__langmenu { + display: flex; +} + +.md-header__langitem { + padding: 0.4rem 0.7rem; + text-decoration: none; + color: var(--md-primary-fg-color); + border-radius: 8px; + display: flex; + justify-content: space-between; + font-weight: 100; +} + +.md-header__langitem:hover, +.md-header__langitem:focus-visible { + background: rgba(99, 9, 255, 0.08); + color: var(--md-primary-fg-color); +} + +.md-header__langitem--active { + background: rgba(99, 9, 255, 0.12); + color: var(--md-primary-fg-color); +} + +/* Mobile: optionally hide or shrink */ +@media (max-width: 900px) { + .md-header__langswitch { + display: none; /* or keep and it will still work */ + } +} + +/* Version switch (mike) */ +.md-version { + position: relative; +} + +.md-header .md-version__current { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 6px 12px; + border-radius: 999px; + font-weight: 600; + font-size: 0.85rem; + text-transform: none; + letter-spacing: 0; + border: 1px solid rgba(255, 255, 255, 0.3); + background: rgba(255, 255, 255, 0.08); + color: #fff; +} + +[data-md-color-scheme="default"] .md-header .md-version__current { + background: rgba(99, 9, 255, 0.08); + color: rgb(212, 207, 255); + border-color: rgba(99, 9, 255); +} + +[data-md-color-scheme="slate"] .md-header .md-version__current { + background: rgba(255, 255, 255, 0.08); + color: #f9f6ff; + border-color: rgba(255, 255, 255, 0.3); +} + +.md-version__label { + margin-right: 0.15rem; +} + +.md-version__icon { + opacity: 0.7; +} + +.md-version__list { + position: absolute; + top: calc(100% + 6px); + right: 0; + min-width: 190px; + padding: 8px; + border-radius: 10px; + background: var(--md-default-bg-color); + border: 1px solid var(--md-primary-bg-color); + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18); + display: none; + flex-direction: column; + gap: 2px; + z-index: 40; +} + +.md-version[open] .md-version__list, +.md-version:focus-within .md-version__list { + display: flex; +} + +.md-version__item { + list-style: none; + color: var(--md-primary-fg-color); +} + +.md-version__link { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 10px; + border-radius: 8px; + text-decoration: none; + color: inherit; + font-weight: 500; + transition: background 0.15s ease, color 0.15s ease; +} + +.md-version__link:hover, +.md-version__link:focus-visible { + background: rgba(99, 9, 255, 0.08); + color: var(--md-primary-fg-color); +} + +.md-version__link--active { + background: rgba(99, 9, 255, 0.12); + color: var(--md-primary-fg-color); + font-weight: 700; +} + +/* Disclaimer bar */ +.md-disclaimer { + background: rgb(212, 207, 255); + color: var(--md-primary-fg-color); + border-bottom: 1px solid rgba(99, 9, 255, 0.25); + padding: 0.1rem 0; +} + +.md-disclaimer p { + margin: 0; + font-size: 0.6rem; + text-align: center; +} + +.md-disclaimer__link { + font-weight: 550; + color: rgb(99, 9, 255); + text-decoration: underline; +} \ No newline at end of file diff --git a/docs/overrides/assets/img/logo.svg b/docs/overrides/assets/img/logo.svg new file mode 100644 index 0000000000..b827f1dbc7 --- /dev/null +++ b/docs/overrides/assets/img/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/overrides/assets/img/python-logo.webp b/docs/overrides/assets/img/python-logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..0a2ac726306fbf836e9fb9174f13502593c85a0b GIT binary patch literal 9414 zcmV;%BstqsNk&G#Bme+cMM6+kP&iDoBme*}|G|F{YH{2)k|Rl#f7Ub8=FC4LCV(HB zq+-7{nvl~e34c@tykpNNif60nok@!fKk$yt!X3PG1FMYsM$HM9swyPl@S%dcte`9) zs>}E>8?Cvij{;B=v?9c$YhNmlMAua7lnIwCTwG9ogw&{w#4 zSh&)IYoRQxdn>!EXDUTy^`P;!Fg4j(8Id(rQ4y$4uV)i1NP3u<*mLp5WIVLR2Ebw! zxOxE^+Co_DK}+ij|1JSvYYpQur_i`^33zG+*xJI@mWDFXCOg0y3k|+rhcvb5UJqgg z+Sa?6HqjeUJ7HFUTEO(|fHN-YDwkD^J&QmuLPL37Xk2VeEw?cid*FK49V)i9J=>EE zCN81A-@Whm{nMzbDkKuk06NH~`*ct^7Bi?0k2FzVr^F-Yro2|%GFZh#kTGsZq&7>Q4lanv!m_czU^- zbz~Fuey)5>08Cq-1ONaGp|Ne-wr$(4+1_%^R<>>1wr$(S;~+tj+_vd)j(-LS5Pov9 zZF}~_bLe&Iz4zXGXY9SVuf2au@4ff7{rR5z2=B}5ASNT14c4sLBLNxASU?6d06S#`E3p){frzwD7LhzvWI|=_HiXdat}D@r$Z(p3(Z_Q7CG_P;Y>o4ZFf0);Q$m`j8{b*i~wQF;FQrso5bahwYFp_nQ!_ITDn*XYg6tG( z7-r`TW%=n31xc^)uXzab$4y*bGoWp-)1wKdKo&K zIHYmOA5?R_d-sGCh_+lVKb-^KDLHQ}#WNl?jOPv0Ys2{0Fv2ik(V_*h8bB;fjaZtR zi&Sh)^;nsjmg;a!g|5_ZI?C}ig*s#$swiw2zhVgf&rUq1#rb0YT z^-J68nYLBCzSU-JSaxoh>x_fStHQq{jp?oN@EpUm+b~|po4O1WuM?{Q&1YhyseWqM zT}@R5u|jlK0e_Zx>%G!Rkm0Umr$q#37^bI&Y0@wuR&)A_hG8kf@EC;g5ynDG+Ywr- zFAZEK;qs?4z@}N)Sc7MJhfQ2;LexaFi-)iYO?3sK1;>_YwK=A$U@E$z>kem=FcV@H-gi z_If>W84jVHaM}9YR_fBqxVWvcdX1-$BEyY(2|0>K+)YTIE#l6EUH3SmI_#MZLJxQrwv z@3vc%X$YTP?|~7Mq-Bj{WLvvsnTGJ`^;AfRO)NnrR5v ztd<@>B;@yYYcmazozepnE$vok8ZDYDIn32z?S`>PTp&D!5Er>w+)SxYEyXCOX$bde zFI}r5gREXeDYQb<0KN&#|GOBa`dT9Z$G78~xTTwwTc(GcbutzE+RyP0x2xxy*2~Zn_7anBFLJ zU|&?;t5>!Dg)8mpgY6srMi=qO*6NXa`vw$*s;QSgkt7?I+2p-`#dVkb@Xn$kt!_cb zXE%Ef&?BFJXsfmk{M!e zTx0hgJ{Z$Gl0c?bkJxJkM3^HF*2Szgg_6&om{P`zC&P2tWa`L!Q-cUfb=SkvF}>=) zf0$P1q#BX>>ko}*^~k-_!~VJRe zxN~?en>+yseS`d^16@^_-jH;*(yw0_(ceB%1P~t*f$?zwcSr|Hy-KY|FhSD&JB;bj z!5Dc05Ler49oe{f2}*HN+qm40QBA2Alcw>$MHP~PlAe=k4NRaa`~D3k_3^!^z$3y0 zpih#4uAZCP=G9(|YhJI4FpbZ=VMn=Oj@*=1?{JdRFJFM-Z{H9nV6#y!P_iMd#X~xb z>~g{cpx1JNlK0ZGPi8^w>z6MeOye^SswovH)t^$2pi|eN4)psE5GS}eLn^j7rW7xw z@uflxbtn6ogfIb{6Eb0^2Ia|=mW>%;b$9c@(-5XU=#5M;E@P6`meoFByZ`u22or!f z%OrwDxx`Tt+z#xC0^94iA3~VM;d$dE6FZ!xb^KTg*xtVX4B~WQiC~UOPwT{q6tI2# z_&MgT3p5otXst|ab&%GRB_e z@#O;Y1Rx?2$jG9!rqoDa)%^e0H-<=_0MsK9%+cj({jdD>3o7N&y*7CQ&@YKVN3Bb% zIdu5~)Q(Ml5(S`Pnb_27pjcOSisj{55D_QMx&@PB_n3J3nb!9w_7**?n97kLPw4Ddhgk{E5gmfm-qF{m)OOd2Az%qtL^TZ1&i40SHiyp z(XXq&eueAX&lDymI4n?5iS>;lIlXC>!z2IsGjTVsCEmRibM1;ale1?>$hxIg56#CC z6B85as-|g29Af|-5m-Fpzhh)(Z8KVU6adT_N!<2Fm#pwuC>kS-8ZBd5qk5)qm(kpm zpxo4cBmO(a(k_Na>6*92+Z>Z_vIW-6>n!t5d(1&=4Ab1X$!4f1lcD%BX)21+R6>-Z z(nSd>F-%YwyBNkP&J3K2XBa6~hJi{|&OqgK6r@f~l^8P#BC)L^F+ zZ>3JD$CWy!k}7pvUFzt_U`Lxu9p#rg&g^-hd_94AvwK)9tP9ni#m`)mXRocZ%#Um{ z+cNVkGlsJm)MPS5{5@-55K%;zI;W2L27)u%;+BC?A&Q(>qqZ%OM zob`oPxZgZAyQk6{l>+kSNu38<1Y2O-^u=WAM)Y(Vc`O1J9XqRVv+Ds%ruozOGqz~@ z+U_VDv{R)8(-<^%sOIVzr@2>^7ER;O*a(4*y{gmVX)Lk`>LU4umV=nz4OFO+y1}K=<0v(L zT#e@%Rn{?$Q)3HMYooFtm4R4gP;G6OnW^k5T8*7mttKijTaH&2)zw4I^p?@^hgQNu zV1Z06C!19^9kmQhtV43@y&SbHxH6Ewx+~n3L1m|{wxj%8bI89smH%8`=zK^7#+#ah z>t|MeVh2@r61&zMva5c`DS8=LQ4xLq1?htQpZH}VoLU&G(epRU@oUY&*OeUe_8DKD zt;aA6$0|vt4$It{kTPpML9z;!RmU+4{#3B;>jSgO;5cUC(q{KC%TuY}avWRhBB}BZ zA)&L`SZ3g-^5e_s48$@E$4gULJlX&>&6MIuI@Wr==Px^=xX!kzdqv9ypb@5wBoNX? zUM1;Imw!6|bPbvdfPOQjB!dtG8%yeB@8JfZex}TxPl$onB}XC9Sx?JcP=WyH6;o!f zCd5F{MW&_bk1MUt5V(QaTxUx0ASGQCT1qE(dpq0!+{%>UHA)PeE=8Yb;tdYk&XnOx zN-nT~v&=!qXX6dbW+99BfHuQ`6elo`gMMxTZ^s*)n_!jk9g!TgC&NgyrDH||iMO=nAZ1JE_54CfK!1ag_yowL3jF^`$c0K9=I zv(FP#Y+cQyXRg(pO-{{(gIJ75WEn<@aRMx+&RH~jdLrz-;C)XS0`BsePI#1Hhw( z>3J>K0Q6urQ);)}Pn88G!ybk;0CV8nShF|z%WxlA#u_lB^9;tlw0yPY<9PA8GiU zi!%sw(TM{%cK4grMdNBx>X!=nJ4S_CeK*Cx6}Cs#%|1Wd?}Yo?@gbvMvKT7b&eto!aTTW zIoA!n<;3^i3^1^E8$B1=3or;zp~cBulM#JSU=CO?w~ad20T@JRFdJ8{*+BR`IlMOq z41nG!ass{}a=Py^QskNx(|9s{Zx)>QUlEmip$j5YXh|O5ZG4~PN$0(pV1bs1zWEPa z5P5xBzPXx?o#TRgbHM^P5#7vQU~NwfM223!if?v!l5%f0bb*(M&Rc-B1w;`d=EZyWUOPOFyf-5($QIH0KC0l7hhRu7_r1GaoRfrmbHacY z*{5@eu=g)uAj*fxg%ocs!}UGF_fr17Sz*AeT=oBzWbeZ6m5oV5|G=RKz*$+QxNGMW z(|D=POMn+n&UkhgI3aW#Ep69^Bx(1r#naredx{0TG=`4{j9?F|&HSn=rF}qRQm5lTKpDcKW6j(+tx9 zHr>U`>x|{=4SY5=MdRfj`U=y#E)nS4`Sltvt)9e^&!}^Ieqp?m;PrUKDtb-W!uWH;R6>?p z3Hu4TrVjG;j>ud>atW}dn6pNoJ>(L`Kak<&)MzN~r(?Ur%eQlRE0@75`EvTs=5rQd zVhR(KF(O3dZ`qlb)V$n({`s770(*bLAVRV!QMN?n&&Am5!abKu&p)3xckGX;gI65VmdlCzoPBpL;pQdI z&OKGm<&<;rUNLfVI$q8fOkCSR*yngbX)hRC&TS~?j!aEWiIS6Z_9Ctja_~>91-*>H z&$TV*=9hD?xw%tQQ&R%v1Wu`&&P*ZX8SN#bD&orq^EKVva4%Tl=3R7ihumCDO-+f_ zZB%Z_5==~x6?sDa<+dj1N_}=$R({a0oSRk7UE}6eyScaByx(pfqW&jd{W;C5_gWkw z4`Qf>bM5VFev4ETg%ql+jU@QaZ6p2^}ve zp<@NbbYejf9m_AGWBG-2a()3FB&<#!=zcxWD=G3cuFUt@@ zG_H3%C6)TRUZq;KA|b5Y7gpY`R{pD2VnwwA356ASzyrc^Bo>yTrb-#2Dy2xQQi6Cv z31S7sNGvEqEWZe`{6Zw>7a+m z{KtYS7L=4iffpAsRcy6X^!W%Q2zm8$+{b2B$wDbB6m)SBRmE1>qUW`IAS-Wh&kc3* zLJi*b6S(Tni58uwvB9Kna!;X}7Ru`4BC?!-kEqSxT%gno@QRV)JT_EmR;Z1I3Kp^D z1ni{Ke9Ht%b>&v7bIzP@r3`g@ctY9_TA{1U2|S?GuO0Y~-Ppebg&I7WOu&8PE136!K2jQWAX@EzyxO- zcc>OwxAzLfkP-cAyo?LxMorLMrOi_AvQStv!6p3c9xS75rnU$}z?!R>d~@-6MCc}G)3 zN1x=#6dg7n+36>?9=%kJ(T9K?@J(Po-1IRcj-B=qsOFg zvQG!S1#bqTXN+ERBt7P;V)hEhprd%RU_eH?2R#<$!W3LS1s&kcz^|iS_3KKdGn5)i zkFf7fB!n;L7m4s$=#pzq_&K*U)YWWMy-IxUnQWPYa$UG!~uGq73arL$~W zDE*u%xZDC<7d@Mw%AT~%1yiD<+n9nDjJM-&F~82H7%i0E$`tfQyme8J3>$Ink zA+}4Hg1(NoQY+8br^Td@RVget*9rd&x8tuXa+mQpQpjxmm^U!_HnXyUDlo=T~7Hcts<3|WGU9o!6rUsjGzqbRW+DJ_{ATm6B-dc6G1TNmtE_4aDD(%*VpR*#bWe$2Ay>WpFOUVFeNMl6fs zq@MKLGhQ8fLODEppnbUAzAE!9jF-CVY-+|Ti*9;WE~zawtB6zvg-d-pFBMTK9HlI} zG>}DVEIIuZrJV3f>U0N{PDCh+wo(hZ)LL?`q*5e4)xHHK`ZO#$S=3ki?sQ%8XOgOP zDKc4vG_dgm`qSlAdL5T6jA~@t0a{^GWnj_59%&+#r9`CHzDpYMB$bZEqpwRty}4jF zsERBa-z{@%;13im<7&vF((Wu;2d=;OrV z#3VrDc6lHQpzUtGMEXMPt*H z_NBhAJa399PC%Uyy+>M^+Ra)umSTw$7oDIjZSB=3CXI<0;=~gt`llA6c5geSZF!

uNQ)>x)(rtCF0PH355SY|Su#Sli8En#KRB#P2xxMK-~3GoSv zNmNioV);cRmS0HNd4;4VFP|jl1xb_}BsIBtBsn*iaOZYOjyJnYl8`5Tqswq#VzW9U zNey;J7!7tp5-N2<9$M;{)K=>FQK{n_rH(sF9W|9YWR^PGJYat-1j2$i zvR2S>{yT0K7+iNUy9>^U|3>^b;=f}U&wv)vFUg`zbU7sQXynn!A(M$I$*O3>OgI|O zRwmiHB3?DV)%q8vT7ODJq}u1Gq1XI6z#^oZK68}GAr)bF6><<7X|e>f zs=Q*?olUmkm^>P+F`E#R%4c+6dzr8b*)XvZQI-;#%Y;(IjmeeCGQqUgn|uZgs93-W z2s$gx0fv-?Ph$mjX~p1JW3*M{M+T{I%Ydb;k}P3ZX$Ulx0ioO_oN8}OczP<{EC!Zh z%PEwHbE=RXQke`gPp*MbxcD;4Rw9DLKFz2yasq@)7!_|4LnT>5<;e~Ze$S{ZY*@dk zJXrxk&}m?db;0=BxM#8bW zF`o*#)Tax1X+)5)(eIScVN(_ktbBSzp2Q0j1-*yOKNN2Y)&-&*J7Zy>ePNTWR0PVW z1&t@@=dtiAKF>RMLHBqx{}wO``W%}Q%tK1C>k&;(e9$m(`N}2(QaetycP4-+_mCG2 z$EsXGN7%gXG}$VgbYzcca?&MmG|+3<)Kn@3rP7@bM4sHj!$33S^S+aiUJ;Nu(>xka z4pYyF1dj@BfY1BR(h*?fkn@N#@Hn`l{q@_#Ah_0u=F}dTXoX5k3BXf=L4{iP3RqF6UCBd1t`!sB+>f zpa_0t3fdW`<4z@6Q0)WZ(Wa>mobjl`xKJW2&X`XgT~5LT7z4l21Z|z!ac6}(sScHj3%{Wy1DRhd$m`B#(&+UB zLP4fa-A1~vJ8gl*8j)hh``-_`u3UT`XM(L9=yj*Pbe1^;1)GBQNqw(7pGlqqjwK(c zSDj2s6nHwUB@p0IZM;->H^HZ%%FqY8RK`m^vzSB>$_A%C(5o(9n!Zdh%7M@Pphs1{ zvB8g=f>NgPL;$y%(~w!I1#X>fuSF@rX>YszU&sYOI$s zcMDtz_)-9WmB?jiz2qf`<-ivLc-8U0gXHq|21!dWD+Ct{U{J**mzzH?u;qYS0en<&Nl&37~znuSE2f3of0LJN|uMKyBa|&8+hN{~TKH*vuX8txPSz zmU>21I6dh*&vD1ied=Y0Hww6I_7bab((60t_nmL};^vN)^Qyd{dj@f{Iz!*ttFJ8Z zRpxjski zKEX`JyS_(cg%?hJr|iDdF$c$;+`JENaL4k^GI?*ajy>zFQmx!stzb3vCvK4E1|Pcl zWq!~ilmCXwZHFog!}2R(#Y9tn;s*I{@O?S|pcjmtQzo0KLT?+YaITb>h2=NGa&B|+ zgWtV;$`39Ig1VV%6n0msQXU(Y?+MGF-k~{8c=;@^px)1480MQ~s?rwK@{q86Q?>j~ zSU%R!y!;tA|B;u!*AFI~Ayb`>*j?dIhGp}@GDcYTGA!dXAg_Sy1>br34PJhpTi|n` z&LuKsYOA3V&uZDy`-Ei=!?NLq;T25!1<&0ArdzPs&3D@>Q?aT=`axNASY95MHdRWW zR!aZO)vNdgzy17segV@jDDd(lo_C^5@hVp+1Z6IjvW!Z}+Dd7CrSxW{^i!pDtgigR zA;0i#P_U!xm#YVMx Mg*wk(la1J$0EqQFX8-^I literal 0 HcmV?d00001 diff --git a/docs/overrides/assets/img/ts-logo.png b/docs/overrides/assets/img/ts-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..77fbb6aec24d581aef15f019ad323dbc56c383de GIT binary patch literal 21739 zcmeFZcU05cw=Wt+0kqbPR3xaf%CN)Cn0fHL^r7FFnpnxKvAT?AG zq$9l-1wto4XrY9=R`mDY8Ry<}-g$qVG437jjXmNf`K~h8T(f@G{I2KPnkuw^u>65Q zAZS%@-ME85P}IT?H6{3ExBql9_}?+x>l)V)h)k%@VSIQ1Uvz) zz)t~l2!y*30R=%i2t;^ zpbyB3;UnXdzwoj|eBWqlhL74E0ekz0<@@h3vN-2VdDjO^ z_hr^U6X?wgS_UFYJ3*wuMCX(uK-cbai*NQ27G_LTTk?LkfP!I`ex{2qxS`vcr z*Vd9-{Mny3#$|RlFGf(Ur9SGjA=nnCjCTX+B9e^FrKN7j-A?Ot@5Xb5&1 zqbmDyC?j`bTE+$y82y?luWpR8PE~eJ+=Rn?uJ2Bv7F($ff-Zi}Z@JGYaLQ-g;LUo} zo0R##q!0)pU;DDlx-on$x7XT*+vPcTmkoI~s3&FIR+$Yr#!?<*G(xhutus9pK+_M# zQt!_3=6}$mnn1OyaG*aSICcf?W|~9=_u}ovk+)yEjQ<2ufVoH$>X;KZW6PNCH%b+i zaU~%5g*1}XF!yrVvV%X$fZJ}(1Bjs4z1>z3#<00o#onpnFYae+wE&dYtK z*!fVnwz?dDXse{-XPuZ)mwX0+uwcC0T32|v`t#1x@k6PY0(y?ZBXamQ#mWoTGos2O zEm(TcrgSb}kMGc}T_xfm1u;$=;osRnpnT7-s9IRM%>gD_F*w(d+Ly7LvUqr~!y4Q@ zEB_=vo}Z7(`pL{rlbt7z?fs_> zs{w1ovr&&8ttt4aUU0k}$&~eqYl{_H(LT^wzo}osOXxEM_l*d*NT_(}~ipB09 ze=IOGh#?t(!pq#6w9@GMcpw}~TKC}E`dg}q<54dX^GOW7rw@=9 zrmT=w#?&f{>tj@_`=aMa3e8iMlc0UQL88g0ou#RWydH!AAEEP}m(v}#mA9bBU)C;T z8K`q@Bc?TD&RAkE=w)`rA28ADnhu8oe&gvt|6N3<>{MZB^v`<*0$?mmf2}gEQ}LjC zqE{Kw3CQaViP7391WL8~*ID16a9^PYs2Zl-?dt37@f45ep zdT(8lM*sbxju$(eiK&I#I&r|5Q9sNpRUlDRk)B?J3$^_Mc zRKMN=2Zex0e|#*Omgdw|weF?2V7DxSxuoV7^Jvr+zh3NqHf z0q!Vw%Vi9EEq5s7dS&~6B-&oB6jBy$Zv|$fHWP>fdF#cQYgJPGhtN?!Rn0DeULH}| zoZgLZ@uP;Ej@c#@WFb2hSN?90w(~4toW(t6M~)9{UJd2n1pGd8KFmJmP@EJBB@}_Z zri4-2^pu^VkY9M1irKZEP<_d31{4k9@l+&H<}mE3Ir=l_tWN4t`9t}WTI$97?E*e2 zz5?U;fqswy0Ba{fYlE4nlq_-J(N|faZ@?GBv`FTVooo&Ad?Nl- z(ZUCMVhriyU91n5ziTOE*#7WV9oB%qbI?wTaLuNA6Ky@`2INN5cfJ-0a1_1G_VxpY zrWX*}8}PWgKjM>Qs{3k5Fd>?Ai++;7ir<_bZc^`yMqFC^A^rzxI@tY~SKSC>#G+mE zF!xa=u=XUKtel8Bejc-}=Tj02y`6sdR07aOp~z=I&k*(+FAKXzk_6=|)AvrNdG$9~ z%Ak!Tm*&QbA#Xe{>*|%dJF#GwL^}u9OZ~@{ZZ5~A;W~eHz5B9Iq{3;5hjU?8{>ETj ztVqMjwi7@%`E$?BsJZG7?L4FKBF)DiIz*k*1rn~^8uG^5tdnzm?-_*@?}WuoFhkHk zw^=6kpB>%#zHLU_VPLlXoBX55%nsMYLGT$5sQ^~0y-o>E@T-z)@g3p-`yZ1$Y3?o# zci1dtVAH6KHWxv!y6t364+L_>Zg-ZOHVaDiW!_M+t7D$KXbukqBd^&53D`Izqm7S4 zAHnI}-*@JY{+0-^6bL09L%l7t)vc#f93la&%YJwbopYDSBV4(2&X2zV%PA9}D>q>R zn$lSJ>6!0KQjk4`;kiWTD{#=yg@cPt17>4eua1lk7ZKf+Q%E#mKTjLH$%$C@+YF?9 zB;If`?-<}q>W$SiMl9Xhyc|25u@{(!b_Z%= z1Y4~fI&0JYCbp{UXlUZ-_E8hp64OX^R3z_@Np72`Y>Ydvm2BTFszM5xR&5^?R~00! z?A27|c?$K}&mX@5d~5BayS!1KxROQgTcIwwi`kAgWvN#m;-ha$+B%|jWrkTq?Z5hU zjSOnj3}FVUAKSyx@@yv`UmG8le?dF4Tj=6|k#MKAvNXW-Bj;PQ^7lyIx&}3pC!mE0 z`X}Sor3m|u&o2Cl3MJw_--@k<2jkRPN0RI;jYY~ciJcMO`-^amdlA~6pXK*sm_EeO zeO=w<_Z#v$EX9wFCif+yId}GO`A3iv&^|4l;@5~>5_P$;l_qteh$p=1!*i~}&NuXl z($(Va;m+xVTjF{l>P&qpCo+?YCSppc4!q?L`aTTzf`NQcosDUu#s27(@$b=R7tw|G zx=6}Y|8Njm1hDHeG;g@%CCV1dQ>i<2l5|Hz(5}W=5q8Z&(l3mojgqe<%FkCT`tH78bU;H^5D?H!wyiol2D!iA?Ny`K^sPy1Zvtm)eZu z@v>i^NzDU?a}&klq4CJ(j2Yt|$w{9FM`)JBA{8GwUJA39I97XVZiT(AAm14I?8okL zhnH+(epYFZCI_z$V$@Hi^rwX=RW4=xW#&5&XY%Q@XgvQ|inT+9?)$eDKLx&jOs?Aa z)Z^N_)D?snJd!K1`N!n_EFjq5+UA?4W+U3C=-85v@d~3W1ZvAaCYN)%zalw`L6Wq4cS9x#G^RS5tXvuh)M2sQTZ;GK;1kn9YblSc9 z>CX^8a9zqW;zu2fjjUsnC2^i=64u0uWy(KmL1w=yE~)RjPqK9Ft~}wrKl;he?$4^; ztlMv!Dyvki$Hz0*`?K+>Kup%L7g-64l1^=#d?hk>jiAPu(>>4JVouHOOn$+`E+UX= z}VgV|P@o%hgGmbHehxj(8t$i%BYX!KDj(>X994H~G_thb6*3n3yYhS$=F z=I^nD(XNzuIS+fY^}%;J7gkFz5F5D@7#HOAiuS9b%aeHbDxJ!|X9q72&#Zm~=xF|tcu4x#ZWW;Vmq`+a^?GQjDaWbwL>Gkkx7O6qr-V(pT`Z)*d)@XHm*ugyd<& zR&IS|_9jkcy}iRrbCle@a|##Hp4d6YqucnI>G#}gnMvy_w)m-)4(Kvp`SSz$Rao7Z zW>##`$cHBS8oRyS`)Pij_O{S->KZ@pn3Ly>1ar04)I6+dOZ<7Nlic;xS>^ThZyK$v zX)>Z3w5RsS>y_#4AALcWBEthDGesByY}YlvVFzCa1yUhJA>Jxmjsj2?AmhG&#Bv=k zI4lTc=p7YY!h*IAcY)XbM&-PnsIE)7Ae_8muExouq@uiQ+C#ez!`Jx4S_iaGq)bO45k% zO1J`ocP68)wC?~TBa=A-$gEyX3T*f_x4G`O&(nkgh0AAD00sycqn(`EWf%N5`-@Ocgo%Y?grn1^C)Bi=W%)#Gzw@3$1_hvpOW`-RhuXR8+ zU7U}HO|IiKnOuKh9&`ymr?Oa%LT2|Cd~0VuafxpdBS=SkpWOtA-4ct+im1%DrIGv89?$FS6Z6OG^m0`V@YkZ=U_Q2O zRoh3sDXmGWD^xc|)l<}Dy?qxI*LWeEHuiI|p2+*VryySjPe4O=(<0buNZ~~+D;hdh z=oD#<_qvDVU$k!@_6?1tYm8797Ta26@B0I<);-?+q9iT|MmU38Sz(-gF)m!m96MW2 zUbZKSWJ#YtjW)dDQgXXZr7&mZL4TR))SugZYZA z_iCLFIXQdA6AaI&SoJ@l zPZYPiaVlXr4S33@!ceo!ipB1(S7u&fe!#T2#L;xu(+wA5y?x-`8I*Q^4PRC6@K-3d z#Aa+zPjMQ4!=czv=g}9f z@$R^|*pWN@PU|WTGJAztMS}68h4Y;mJ0Gi5W>yn3UFXcWL_K$##Kff>jskTQdXrLN z5kepI96AJyd8xvo-@)#OdlQx~*u#FFESPu!KiqcCAEsY1FH75iAfX7U0=)n2(_COH z?T4<5-n3cy?4i{Asoj)<*xcu^9@?;2v^4G4zK=XWQ_m?@!!wgEX&@F&H1Wdm*1wg#L?h{Ns7} z(V$h17_@ccko0uqQ1o=P2}6pX276%PnN+$xr_S8-;F*j|eMlbhtKdq@PizTGX5$83 z9Np;sy-dcdoz>AJ>(ff#X6J*on%Yi0U;-Tb*eZQcu5i`7R6f0Cbp`lnN=q90(t`Pp zWrqsXIC91Rub^~k~mCCjbI7!|}W%=W9 z;)7mDiq|s)M@xkd6=B|dESA%>Tp}>-zSy+o&Pm3xRASN1*>V+)mS{TWbo%zQAkMq* zDT|l%WPKfBx=+fK-$T(68#3I9!*~Pcf8=pZem8CRb1o^-=m0(>7WqFyuZ)d4gvsc{ zH5Yq2lRwgmSWzu`H{Uc=@0+#}bc_pBn#e{=Iws2}=O3cY#nX5DOr;OkLGV6jTv~yq zB1Gp7;CKuQ+Q)&v9nHKnDZC4ORL6w-ug%;H0nxV!Tc<@_T)l;Ohao3wg_9xzij znCWrP2x@pum+-m%(wnX-xrHRYx+4gVx0X1!H>=`=7i-IE2D9zvSmpiofQx+CbrN2% zwMfC$soKB!z1yY_5?D9{={*Qd!HQm8jV{7?*edwct?P}=B-T7wj;r=vXY`ygp*rD zU5aP|I;hlJ)@knLS?%&%9%xH=FfImZ+nJo~v~ZxErdlPLSHQ(&q*C; z0Vl)>3i;x(x9>k=aV5=cvpi0k@$QB8pegCc#%xlzq;~sLNk^e$&{KK%AR>{%f76!x z+SvjHr9A?DXDUZ+1Y#gY4LM?U48|Etf9QUbIclPoUtQl`0KZNO|i9c~-HM~+>V5I}z40{)a)XD? z8yEF7syJu`nxK2E73ktFv%jqtEogTHlIn1DkbV*bM(rBSWYT|scX2DC|JV0;?P4p} zV8rjq2KE8* z$K?!V{#rw-lZ7^7AnEvCr0_4IeGsxoO;8cTwr-8#8*&!pPNN8qV`W>_Ie82)VW9cN z`FG}sfj6^?Hif^46LsG_#qyeRS+Q82U|Y_7j?951=OZRXW`1AXxM0j=VLQ~%72we4 zvKQI>a!=|H8uAV@)Kc8cxsUYQ9e>B*0fWO@O==630EZ#qT-zqf&yz>ur~>drxc1ce z{^u%DKgZDXkRhuNH)!>W`s}`oJ6Sm>btpI;0!PZo0v8_H5|kHlbf6;8HmuE9b9m%5 zWRRCw|H;YoKR!=oO97CUlHJd0h}wirh*R`@%$S%B}CbB>v^Ju+I%k zg~NqF5%;j<2Qc)o2p%i?^o?4n=}lKVaX*)?rR=3fBP6Ew)bUlyBXYfMDc_T{s(qb@ zlUT!!fJFxcvjY*OQw?4c7vc1qKf>I#)M^1|mbh%I0}=Z* zn9{qr=2VALR^Siaa5=t2_h2hml_Fud8>`xJ<0DQ_&O4^7a;?V>a7G!Pk-u;PT0%@u zAsQPd^i_koCrYqp@b3`A5)GHRf%bl2dvCsyc9kuZjj)IyRD;Cr=TSV+pt*J^T59fD{}R1bPTL3$UlBblyM zQ68;-Q*1Aa1xlLGC*QHH596Z_&+cb^dfgNnnVf{Lnpu@2)qeUt>;4ul{3cTt2vpi( zJ~ms0dj*y0G+c^1N3Eoj$QL2cjim_RMUCK@l%B25USWQ6SMBtC!|IF4Sh-VnWqcvi zyulHjbQ8jYNNGD8fc%9)i}9*jFV|Y2yidnsrDs^LnJ-;PUeSBDvU0AB*UovvS`v~k zv!2W;a@)Iz zPy`wQ=s;6RnK}@f;xE7-koGDzK^P8&V>?w&R?&B_QqGd}Rqu%qoagldW9V@qIwu_1 z%(-4^;t&=$3lt^mZFBq#6rrGmWc*Ov$bcK`Kf%@j_p4kqEF#mQ#vv=tmE`Ar3Mx1? zvF@xxSna7qu?lItFYd$s05-C1F|E=7W_9ExZ<#(?u5jC?W%-9)BCATcK-T4^fY&y? z_hQd>2T-Y-aIdwoFaQfx&OeTO>43Cr;^R={SHx`76DQxHL~LD?b)XvbW)TEy2B_ui zK}eY7z`INu>g?h*BRZ*p2`Ts$9K`jlF4+Eo)(qR#^Q0Dqm ztTu=grUv+E>YT;h)z!v#H>wB|wleZ$33lGtyO``cW}1K8W*g;0miV!io*Gw%1bGL5 ze7Sbm?P1YkP?Jp^y4Ly2r{gq&EF$-&#xgN3yDy=7irNCMy8%oS!wEe)jbC%QL4q;sq;llfJY3 z!86h-nzvDzPoPYEq#!MS^DJwOIzJQeZdrPfxTmnn^!8;Q?ak}ZaDMMcE)yIrg5H39 zb-m(@?R2~?TOuTj-DxE^6zIw1`Te;TaS&i+pJ$31HfC9G;Zg6zr25|&Uu!c2GCgz| zs0xBqQK&wCc<^@UW8MT4jUlvh^Oo7TS-ippAO#V!DlnJYSp*?xr=jA#xWdoJm5gRnjYwCrYE*NSIAv_odK^#rh_I8lL%CkJ*B_v3*6LHC>TBWm> z)2nzsvmArwb2M*!G+DF;ZT$W&<1yXfA3EH?^!obmL=d5=6}7A+&qd=9FSy*sC}?I! zy`cDHLP0QF(KcP3X=Y6o+KBs$Fbgs_Ege7ITbvbi0b~*v87tBL(Bg)14q1`2;77V~ z%{8Retx>OS2}|wmBvwA@nS^FyGq5LjwNlb>H=q9lEt0;^UaoiRK-_d1t$d@!y@x=} zlhY(b75xVGOk3e=c3O;wPoMohjTe~nU$XL)>bGQ=`b0Oir z{eDhXU3wV)X|yOq2O;W zz$`BKhETnU4tHmYqOhX>xBV2?HmgVtSZ&dZI)>TF_Izd$R25Ou2vvqSntRH%^dYqP zRl7gVI;>aY`P*w>{SgEacOo)9-az4gMY7d-NMIMh^wT~43H=*e=o^26WPd#_+6Jdq zATI@yB_T3_<0h`HS(R&iYK3{W-I(AV_W6zJGI8<#f@&Y$LXmnPO!?o0q%+W1ZtXAlEq!X{owb{7w>cm@YZ) zdHXXeF>?l~p1Q!~TAnVOfFToKf#TQpPmpJuxZShH zsA1cJPQh~pl9Z#!8eS*j`XXJkLi9~0B_KiCS^!hS`Arxn_0;$oOE@n|QgbKDWL-4( zSw1iQu<_Qf<-qi+iI>wn1wb8*OfU9UP9HoSV2iQbCM0l^SvFMY_ZR2x8oT%6fO9i2 z=9Kpb9l!}EjD^T>IGL8YC}WA4r|A^}ise2|w8SlhAMT80>T5RmT!!+H3i1_PpUK^Two;- z4LD;|Gn2#NU`zraooG&+Find0TM068SINH4Byq`8Y&NzO$_|gziqWbkS;*aa_TO^XY|QhjcM6E$Lp-e<18ruV1Y0?{^R+cX%e0P*N}v zb&-#qK1%@{eF%0=45Yq>ZT^-b9z2PzipZQ(AsnWW`>-n~wA~$I5#6YPd zy_5PCG=AA^^3nsNpDuy`Y@A8F76c3k`$qoU3Nn5q+EIOJ*3?Z)!jqQi>3MwHY)40o zFhBV$Yc(GFRj7eHseT#|Kq>drDAi#qyjdbK4V2xylM0H->f|ovd-C>e>JH36UI~<2 z>$Y?Y(8$B{tr}TyjIbp%0QH2>vR=(Zt0U@1kLbho5KYn32!qzw&+u2Z(lkiqi5vAlR0}=cq~(=bGmq65a|F&qD*- z>O7LNQhnWW$tD8QC#nAd-wbgnt-V!0&qy<$0<4NI8VZj%PlwPGAn^ez_(;!4{~y`; ztq#C?2~^%!qNGga)L8avUeg8XnZDAJO~=V2Kr>8HvvDTi13`ORPGMf?!2zUATc1Yz zDd+;yXSi*@r_@=r(RrF03d)zDyaVC_ULQ9EU^Hk(^6&M}XBjT(@NkGI5Vkn1sex)E zu#L4Ai6@bRFEIPv?cQD41+9_!Cedl6_xA_6#(lfhxuD@3+yudHD&4_OgxtZB!}`#n z*-Llh-LNmt;+Xz9xgWKkelZU1=0P{zT4S1M>pxxHlZga@_T?ps0`$5WfL_Ssgp<5{ zHuw}UmS*nb;pMAAwD0syFSq530}%tK%#Ek9kFnR_x$Y+~V*gdMYFMX$!$%~>0HoqJ zkP)UJ)1Sp4X8$rG!TNv^bqt)LlY+oG#QMB>UQuAc79oU zdFP$<{OSq2oU%~*$c}#w8m)lgFsydQ3VYD20K+gzZv?P0{2{4O4sRJs7<;hFl2eo(>ybAYz*56G>;UM>{b6i89Ph;hYcV3^N8xMHx3?OaugRvI5*->R; zcLQHhRp(Un4hkkxb3>W5(8Rq`0PA~kxU(4o8aWU$`3Bw?@rQq*(3G>Pq=yEsHy%Ji zgx8!CFByFoDoi{^Yyw|!dw+RssVj979_e3`uRtwt!O&(M8n;+hc^SL1WT^^iDosv1 zvcPUGZmUVm#6${qs0iLm%OAfUNMjk9F56FL!-Dal#V-fr>+2#=;SzW~=p7FmH@P^2 z<_v&rX40$OjmLM3jSI7S2!X-L2ic!(_nR*L;*bI~Gh_yWP{yTb?nmb3C}NS^DOEsN ztx!*&Yyt{XEmxp`Zyf#PfxRB|oJ*b#BDl4W+{a9zKhN(p@W*y{SsV$24BPDop}j2$ ztxQ@w97`!SHeogC+)C|@6J8GgwWXD&?kcus`}2#0U}H( zD4hmJCt4HN`u=i%xU%u`CUmsdqGGJqAv_+NULy=n&{*Ddu!&WTk=MVYTl!(4MNI+i zcaDGJL70q)XA%Nh)LL^0p(^^@srr|DRS7SA{o2*etoXhe9^W8#YJj=*p4g7Z0o}C= zllgJ^BOo8aal`OZ`T_o|^deQMt;KhWz~Bl$5P-s<9YKmqH!YIL#>`64%YAK6`HRfp z)fXTww(Qtn>88FsW}R_JdQzrA?PMxH?7Vx zmePOe1P_p(fZ*kU0c2Cn;k2d_jj-~|Hl|szhtNzdy#Pt-CG)jsZ_e93P$?qI(#K4g zSObVflIg+a+?rrq%nrh<~>efum7ygOb&y|NPx-%AinrrT;BWwyI7+( zL@A-KTx}XFuIAw+CMG|ieU9*;{k8PebaSi#IPPmcE$+O3EBo3>pg@y4d*37RP5o&{ zlzKnD%nK)PMr~%XvzmGJh9XC}-pG+r3z)7UmS`pn%VhZax0(J%z@D$FH|gStUz9yr zGj4`Iw7&(A1Zb5I9zo`&HRt&xW&SV;4Y^>4bYUQKM^?Gm2q$|IFMcEZ&sw-agU|gv z+J`}96Rl2Q5`c-Jwg#kvBUcN6KcOBw=wv#O*YXi{;M(QG)%yS;*(60KL@!=&B&GUD z_VocXfDDuQlWGt6AURsqe!BQvt>$C0baZ(3EvMehDF#UKFA9L>ncmD1hHx{PfFWnY zivbQAhp&D~lV&McbcrLU&<+0MA6cVeIAJkxuV={iiP0aw`T8;UXxRXDF#~{4Aqy-9 z2Fu!czZYB8YJ7xt;G@IF1|7@mpbc7T3qa||`hmvE$H&EHQ(Wkc>e< zKr}=byuF8TwiEk1d~kF*$O^2-g6>MlbgWiFT4ar*^RO`+Zzd_s?O2(|(X!kLxL%7+ z^!{T@0)%Ior%V~u{g~yy&`%nDYM_U-YV+aL?OG)#ydG*w4Z7F$stPeQgX%XL9j+Ae z&e*qr(n0d{R9dOg{g=$0g+DKgSNFX;5VwlfeFYC{_Cf^+`i*sE0wK=^XL9pUGc^tJ4GSWABL+{?u z@Pnx6{u7o$AKi4Q7}u83aCp+lsm`vViF8!6?42pG=OWcI8Ue{Ve6t$DVYD_S6P*4?Ii+INl*iW5<$(``fJ@;GKL7X2PZ81BAvFPW;8G0Z~$+3y*I>4H|+fpKc7smOn zVOE-dVxI`n(I2H%?%2ip5n`0&*K_*EDk@~<5AKp3B&ipqu~u~?%fg-fJaT9WTru<0 z8lnHI1gh43TB$C!)RTn_*;(M0<*%gs5=Q~P5R1QR0?{W0ia?InU;HF1cYFD8I9P#n z9vrer)*VIUSVCS=nF;YI9%gf`Zv(t3LgJfZP!TvsonAyr>Fu97e-LPWPH^JEv(&GL zM*t@uH?y~U6MAfLkn7N;4EUE`Y3(n2*YRi_lpNwVIhJ4b4S$w5{!z92-keF+jFywH>11{7KVP=wh}& zLKG0a8E_!q3KD)b+wB0Cpd6TQMcB5reA;tovZNjv7Jb2rAGd)qPHp~2P^PlqQ#3;8 z&+Y_AxiY99w5;pkd=}XJS1v&T5CYxh!N&psCFb^9p{CQ@;8{5u3uMN^0A}wlsBbv% z$wIzLf}j}msra~OKa9lut#r-GEN+{*jrN8)ItkrMEnD5CC3~`^W~ORzI7^z%3NPR2 z*MRuwHT3r-a7@(=YU)IB8n;lHSlNMS{t+tIhQfAolmhzr!=-~_lB}!I#-KikuGG2Z zVyRz z-i`au;YT$JR0G>~t>=~FI{3?R5gi}q8NSNecTAV0c+Ks|9ju;6lz!d!SN#p!?Q8k> zaBC_+YXi<(f}kEi+BY--N*HC;mo*M^ER#}S2WPW#{?>jsZ2j_KS66=mK*y}={4EPD zYJ?L>CTnQnhG|PUIjUuarzY5Px=hgj1hF_wm_S8Eq18+Ykbd!{3@-pR z!Wvyz5_WQHv8hhjh#bGpNQ z1iv@yJ_16}&zv=I6LCOQ9`~r=UhN&OPzxRoh=ZDxLh&*3uJmF7yo<{EY~2x4QnT|3 zoOl;L@Y4cmQF5{IZlQ;oxju4t0*M@~u;py-1%-Ry+^LOeAPE>05kC`$Ef&l~sco2p z20C<>u>QRoKUV-YDge}Ri{9@Ifz`?J83R>C^nN1MiGWPyHrZ+g>~4WP#A*{~_WNs}q_#WREg^bqI88oX za*#3I<0B7qPYWY%?(+K?R`AfnTEcNzk{qk$m~T7IH4k8FTF5c;tLjvA-8wkICew;o z7-*10wgJHx`Q5ncpwD;zpBeIgAU2oPKvEo=?DMb25GuJFDG$q^!K-{gNga^5qKZLYvsQtb136*Ru5mUViv^j>=)d{{^9Atb5?Ct#i+#Gq>f?J=Zw<@4+@Uu{ zyoyNOPR63<^OFBXF$B#Iu{#{US?J!!o(l4U);m60l(4V&Va~lVecgtt?5T>e~C;<{Zz7c!T(4)Y?pUjWc3QLef z&hx3c;&Eob=LVimEGKTn|-VTpujABtU-zA}v}9tPU`* z)mwXaiCb@T!Fvmd)i8=OeQ$KB#=MXhQ)aEJDdpvBMtoui57O#u1$u$izzbALPLx^Q zEpgnw#|22Pb*B3Pt1#h*BD)lxX5;LFHEvld-DewAmBCW2kF~C}dot#0+Lo@uD*7cC zHGPkng9-CEtpitO(u#02;frOql{!|iYVzf9Z(lmzy!z6_ZvA`5MHdPgFvGQWL%`$N z1Kf)5vL_#^`^OnjM#=+gqG>4TdQ8Fl2B}YTVI5so>4Z3W2}uK>kWwq(EE)QJSh$9Y zNJ)S|4yd_irXoe!Cz`mUZT;P5l1$usZhE@I^FNxqphB?|0)Vi@5kO@w-YYuMu1o&x z09DdY_~8VSIGEh|0zXjnz%TOG@lpmT07in9PmGqGw;V}^b(1q-^-YzAnVC55c>0;+kX*5gBF#8}QY;4%J2zCCFK~Ip?`zV&xEzKD2{NC7n)rWu zXzK5}X{3T4;&0&&w+<=1HIK;!_hK+mLU63wZ+-#R?eefm31~?@bc{$4ALfc>>IRt= z3YcXA!C_z~Nmgd6+sq^T0xxT5##P)yui|4PE2#sL}uaibZI2w zRFN;mk|_`tbMUl7S<)GPZbd&E-FTR-0WrHF(RY*kXBb2KFP7t}*M6WQTlNhzQQ&;Sb@KDpXR*694fS_G zl@N$m)=Z5HA>3(HEzT!dff7}^8qn${u7AgwUsqj%3RLw0a=a#Ye{kF7FbsLR8iQ9m z(gL$0+pdca!#AtMBtsrVrIGBRB11=^+*&$afi1}@Le~n>*jXDoJ6#QZP&8t3WQh&F z(E_SH*2;KBK@va@08jna(UJ-}9AzSZZNkEXiKDV78#~cF=^)1^0zB-a5?|+}1!!g3*F) z%d@t`(Krz17UHK%KxNf}u)2~ufHu;?s{ripxpEIH54{E`DL4G&k7d;tmWzqy6gzdP zR7xKp^?^`5;h7$&00FhzK*y{B;@*}dbU~EovkiXluzFxeKl={;I&ifB4dnp^v(2DJ z5VbeFTs}pbTV`FQF$;1(GSQuI+ueoofbI_f4HdZa3Vx}e;k@Q;}Sdx1x zAN?ipkP2ZjOPtb~0({>!z*J`D37@$sZVO`;roI?eb^x&z5=k|Z)-cj3k+j)(_QO4C z6IAvC8o*m)2SdH$FE&9)W}{{fqcgPRwhee+2}~>gBo1f?0FXAM>898|{ApqW16ru>UuGpijve3?KDI87V-aZ&G zkMX?t6d15q3Q85~C5|=tLdDLar}yXcx!-ZC7B_8fffxW>#&GAV|6c*gEkP4W;QoUE zAHBG~P)_Q}!s0dCU$-^5f8IQhYd#z&dV?4LN-x?;0y#u%X51<~wIS>J^4G_wNUeDMa{7*zyV zj8HO6Tqr%nZyzWlB00Jak-VvtU^%rf@+Mr>9S&7Ucuz*m@+`c+XPp~u3?2oX&u&@{ z1y{SI9PW+9*08k3{!BgxXtTI{rL_*ZUyMJ@JtCJ?KC7fk*$!Axt9|DU+bDjkkJEqf z$o@!?=A3E^pE|fW2t2qHpN1j5^P`guh_-t5dS1N;EJ*0h(X!WG-{bg6{ep5o+nz4A zicD#M>vyg#^YshLpzFR;?RB+G?7rMedjK^QokG4-FT#c?p8&2&{==zPVe++8NGy!2-GUiSnFtfqjfpXTZfM0j8Wa z%7z;C&5<}IJ&tz4Y8+Q&RoSf>V>7@>gvZ;A9RHaLRK!7j<}Q=$)R{y~;}>jn+iDbe z_^~H;=DqSPo8m#2e?m*gj!Dw)u;x|IRiYYrxT+l@64>4s#Iq6>S*&|>rzNrzoA>&) z+?X0zW^IRFmhax#Sq`jQ_ScP${ja!m|M`MD3|fRg0lBMlp~X8x8FYePE1G+cKxHbB zl$!l~hPR84!Bekk_rwoIzFYrP6`m0+&08AP`jk@=aV3&JT0xKzOdR>azjgevPApep zG+zAf&`|oUHD1=)TK8pkqsAxjd{9UEz4g%Q66*wdDJk{fH6QjTp=zQ2+d=+SO7qwl zGda-4;}xcLK#Q>#Vv<-dJ4E1K>p;924qLoR{b}O3#0$Osl)jE zNsJzY^pF~0S?$EL9zucqUYV}v8vfH_yW&)LD7@YYDmAGo~4s3+tyKVVFPbVebpDx@lDfDWljZW(#r1g6)a)G zsZ07K?&1u-ss%i&ul5(5NL|B@P)MnsOZD476SdzR3RGW6E|%9HJGXTFq{lYic<9Vw zVQ7cK3bS=0Cwd65F)03mG-hq+q~_q68c%Dj12sW~*)rXbX%j(3pg{+G(G2f=?F|$c z=Fa~_cgie;wVI13tcR)^uEl{lbLw~abtPhAB~1x0Efq_76eBavH6|RUJ>`k(+t0X_ zR3#1?Exh+fv+_0c)V-H#P=;TV(Fw zC|K&(m>G+fb$;>!iy3NE+u4th%n1|du5o6zwLNapsz5l-js5%ue8&`Wziq8_;Agf$ z@2)@jsyLl<1*$sd#x+2j;^AuI+D}x3?AtiSZ|CV_gR8e&zDd%aBIT${kB|HTjnVtU zQIk^=DHS_h-^}h2(igOc-N%_vDw;8PJG6M&fTRk%G?jHVWZifm&2N;?e%WZEf_joW z@vx(n?g|SPMju>oHSPkYLUUh4IxMiREs<}GJHKg2*H<1Xb+8^E7rTIY)AkSvuJ#KU z%gDXlQfj{UW2#1qyU6b$(p(=0FS`mY^wo&EiC2dD``|BNgn$}um%MhZK(SM<`bGGH z3k7G&#tC=M2?~UYc_9IhmclHqQsr8&6*-M1o0r3jsYEso{T7Vb9Q$;Plb zzq|5Jk)~9uhgbLr6MhZo(Az})&eOnldVLo&NiW=e2g$=L5m_egbJQL#e&06tx3a`+ z2CAn0DcJ@FVp0#uWeHsmgO`xugOqV}r3O341$X=j>?oT`Poaj^J2v_+3s54Gnb-Ekg_ptPBjTjE%HG41>t|lYl7 +

+ + {% if "navigation.tabs.sticky" in features %} + {% if "navigation.tabs" in features %} + {% include "partials/tabs.html" %} + {% endif %} + {% endif %} + + +
+
+

+ The new styling applies starting with version 5.2.0. For earlier versions, visit + legacy-sdk.humanprotocol.org. +

+
+
+ + diff --git a/docs/overrides/partials/logo.html b/docs/overrides/partials/logo.html new file mode 100644 index 0000000000..1e7def1860 --- /dev/null +++ b/docs/overrides/partials/logo.html @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000000..206680fe29 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,6 @@ +mkdocs-material +pymdown-extensions +pyyaml +mike +mkdocs-section-index +mkdocstrings[python] \ No newline at end of file diff --git a/docs/sdk/README.md b/docs/sdk/README.md deleted file mode 100644 index 225cab21fa..0000000000 --- a/docs/sdk/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# HUMAN Protocol SDK - -Welcome to the official documentation for HUMAN Protocol SDK. - -## Overview - -- Covers both TypeScript and Python SDKs used to build on HUMAN Protocol. -- Use the sidebar to browse guides and API references; search to quickly find classes and functions. - -## Install - -### Typescript - -```bash -npm install @human-protocol/sdk -# or -yarn add @human-protocol/sdk -``` - -### Python - -```bash -pip install human-protocol-sdk -``` - -## Links - -- [NPM package](https://www.npmjs.com/package/@human-protocol/sdk) -- [PyPI package](https://pypi.org/project/human-protocol-sdk/) -- [GitHub repository](https://github.com/humanprotocol/human-protocol) - -## Versioning - -- Content is imported from the repository at release time. - -## Changelog - -- [CHANGELOG](changelog.md) — release notes and changes. diff --git a/docs/sdk/SUMMARY.md b/docs/sdk/SUMMARY.md deleted file mode 100644 index 5241c9eb3d..0000000000 --- a/docs/sdk/SUMMARY.md +++ /dev/null @@ -1,61 +0,0 @@ -# Table of contents - -- [HUMAN Protocol SDK](README.md) - -## Typescript SDK - -- [Encryption](typescript/encryption/README.md) - - [Encryption](typescript/encryption/classes/Encryption.md) - - [EncryptionUtils](typescript/encryption/classes/EncryptionUtils.md) -- [Escrow](typescript/escrow/README.md) - - [EscrowClient](typescript/escrow/classes/EscrowClient.md) - - [EscrowUtils](typescript/escrow/classes/EscrowUtils.md) -- [KVStore](typescript/kvstore/README.md) - - [KVStoreClient](typescript/kvstore/classes/KVStoreClient.md) - - [KVStoreUtils](typescript/kvstore/classes/KVStoreUtils.md) -- [Staking](typescript/staking/README.md) - - [StakingClient](typescript/staking/classes/StakingClient.md) -- [Operator](typescript/operator/README.md) - - [OperatorUtils](typescript/operator/classes/OperatorUtils.md) -- [Storage](typescript/storage/README.md) - - [StorageClient](typescript/storage/classes/StorageClient.md) -- [Statistics](typescript/statistics/README.md) - - [StatisticsClient](typescript/statistics/classes/StatisticsClient.md) -- [Transaction](typescript/transaction/README.md) - - [TransactionUtils](typescript/transaction/classes/TransactionUtils.md) - -## Python SDK - -- [agreement](python/human_protocol_sdk.agreement.md) - - [bootstrap](python/human_protocol_sdk.agreement.bootstrap.md) - - [measures](python/human_protocol_sdk.agreement.measures.md) - - [utils](python/human_protocol_sdk.agreement.utils.md) -- [encryption](python/human_protocol_sdk.encryption.md) - - [encryption](python/human_protocol_sdk.encryption.encryption.md) - - [legacy_encryption](python/human_protocol_sdk.legacy_encryption.md) - - [encryption_utils](python/human_protocol_sdk.encryption.encryption_utils.md) -- [escrow](python/human_protocol_sdk.escrow.md) - - [escrow_client](python/human_protocol_sdk.escrow.escrow_client.md) - - [escrow_utils](python/human_protocol_sdk.escrow.escrow_utils.md) -- [kvstore](python/human_protocol_sdk.kvstore.md) - - [kvstore_client](python/human_protocol_sdk.kvstore.kvstore_client.md) - - [kvstore_utils](python/human_protocol_sdk.kvstore.kvstore_utils.md) -- [staking](python/human_protocol_sdk.staking.md) - - [staking_client](python/human_protocol_sdk.staking.staking_client.md) - - [staking_utils](python/human_protocol_sdk.staking.staking_utils.md) -- [operator](python/human_protocol_sdk.operator.md) - - [operator_utils](python/human_protocol_sdk.operator.operator_utils.md) -- [statistics](python/human_protocol_sdk.statistics.md) - - [statistics_client](python/human_protocol_sdk.statistics.statistics_client.md) -- [storage](python/human_protocol_sdk.storage.md) - - [storage_client](python/human_protocol_sdk.storage.storage_client.md) - - [storage_utils](python/human_protocol_sdk.storage.storage_utils.md) -- [transaction](python/human_protocol_sdk.transaction.md) - - [transaction_utils](python/human_protocol_sdk.transaction.transaction_utils.md) -- [constants](python/human_protocol_sdk.constants.md) -- [filter](python/human_protocol_sdk.filter.md) -- [utils](python/human_protocol_sdk.utils.md) - ---- - -- [CHANGELOG](changelog.md) diff --git a/docs/sdk/changelog.md b/docs/sdk/changelog.md deleted file mode 100644 index 1050ceae31..0000000000 --- a/docs/sdk/changelog.md +++ /dev/null @@ -1,36 +0,0 @@ -# Changelog - -### Added -- new optional config for querying subgraph with retries when failuers are due to bad indexers errors - -### Changed - -### Deprecated - -### Removed - -### Fixed - -### Security - -# How to upgrade - -## Typescript - -### yarn - -``` -yarn upgrade @human-protocol/sdk -``` - -### npm - -``` -npm update @human-protocol/sdk -``` - -## Python - -``` -pip install --upgrade human-protocol-sdk -``` diff --git a/docs/sdk/python/human_protocol_sdk.agreement.bootstrap.md b/docs/sdk/python/human_protocol_sdk.agreement.bootstrap.md deleted file mode 100644 index d1659f6ba2..0000000000 --- a/docs/sdk/python/human_protocol_sdk.agreement.bootstrap.md +++ /dev/null @@ -1,41 +0,0 @@ -# human_protocol_sdk.agreement.bootstrap module - -Module containing methods to calculate confidence intervals using bootstrapping. - -### human_protocol_sdk.agreement.bootstrap.confidence_intervals(data, statistic_fn, n_iterations=1000, n_sample=None, confidence_level=0.95, algorithm='bca', seed=None) - -Returns a tuple, containing the confidence interval for the boostrap estimates of the given statistic and statistics of the bootstrap samples. - -* **Parameters:** - * **data** (`Sequence`) – Data to estimate the statistic. - * **statistic_fn** (`Callable`) – Function to calculate the statistic. statistic_fn(data) must return a number. - * **n_iterations** (`int`) – Number of bootstrap samples to use for the estimate. - * **n_sample** (`Optional`[`int`]) – If provided, determines the size of each bootstrap sample - drawn from the data. If omitted, is equal to the length of the data. - * **confidence_level** – Size of the confidence interval. - * **algorithm** – Which algorithm to use for the confidence interval - estimation. “bca” uses the “Bias Corrected Bootstrap with - Acceleration”, “percentile” simply takes the appropriate - percentiles from the bootstrap distribution. - * **seed** – Random seed to use. -* **Return type:** - `Tuple`[`Tuple`[`float`, `float`], `ndarray`] -* **Returns:** - Confidence interval and bootstrap distribution. -* **Example:** - ```python - from human_protocol_sdk.agreement.bootstrap import confidence_interval - import numpy as np - - np.random.seed(42) - data = np.random.randn(10_000) - fn = np.mean - sample_mean = fn(data) - print(f"Sample mean is {sample_mean:.3f}") - # Sample mean is -0.002 - - cl = 0.99 - ci, _ = confidence_interval(data, fn, confidence_level=cl) - print(f"Population mean is between {ci[0]:.2f} and {ci[1]:.2f} with a probablity of {cl}") - # Population mean is between -0.02 and 0.02 with a probablity of 0.99 - ``` diff --git a/docs/sdk/python/human_protocol_sdk.agreement.md b/docs/sdk/python/human_protocol_sdk.agreement.md deleted file mode 100644 index aaa48cd386..0000000000 --- a/docs/sdk/python/human_protocol_sdk.agreement.md +++ /dev/null @@ -1,105 +0,0 @@ -# human_protocol_sdk.agreement package - -**A subpackage for calculating Inter Rater Agreement measures for annotated data.** - -This module contains methods that estimate the agreement -between annotatorsin a data labelling project. -Its role is to provide easy access to means of estimating data quality -for developers of Reputation and Recording Oracles. - -## Getting Started - -This module is an optional extra of the HUMAN Protocol SDK. -In order to use it, run the following command: - -```bash -pip install human_protocol_sdk[agreement] -``` - -### A simple example - -The main functionality of the module is provided by a single function called [agreement](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.agreement). -Suppose we have a very small annotation, where 3 annotators label 4 different images. -The goal is to find find if an image contain a cat or not, -so they label them either cat or not. - -After processing, the data might look look like that: - -```python -from numpy import nan -annotations = [ - ['cat', 'not', 'cat'], - ['cat', 'cat', 'cat'], - ['not', 'not', 'not'], - ['cat', nan, 'not'], -] -``` - -Each row contains the annotations for a single item and -each column contains the annotations of an individual annotator. -We call this format ‘annotation’ format, -which is the default format expected by the agreement function -and all measures implemented in this package. - -Our data contains a missing value, indicated by the nan entry. -Annotator 2 did not provide an annotation for item 4. -All missing values must be marked in this way. - -So, we can simply plug our annotations into the function. - -```python -agreement_report = agreement(annotations, measure="fleiss_kappa") -print(agreement_report) -# { -# 'results': { -# 'measure': 'fleiss_kappa', -# 'score': 0.3950000000000001, -# 'ci': None, -# 'confidence_level': None -# }, -# 'config': { -# 'measure': 'fleiss_kappa', -# 'labels': array(['cat', 'not'], dtype='* - -Elliptic curve definition. - -#### KEY_LEN *= 32* - -ECIES using AES256 and HMAC-SHA-256-32 - -#### MODE - -Cipher mode definition. - -alias of `CTR` - -#### PUBLIC_KEY_LEN *: `int`* *= 64* - -Length of public keys: 512 bit keys in uncompressed form, without -format byte - -#### decrypt(data, private_key, shared_mac_data=b'') - -Decrypt data with ECIES method using the given private key -1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) ) -2) verify tag -3) decrypt -ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R) -[where R = r\*G, and recipientPublic = recipientPrivate\*G] - -* **Parameters:** - * **data** (`bytes`) – Data to be decrypted - * **private_key** (`PrivateKey`) – Private key to be used in agreement. - * **shared_mac_data** (`bytes`) – shared mac additional data as suffix. -* **Return type:** - `bytes` -* **Returns:** - Decrypted byte string -* **Example:** - ```python - from human_protocol_sdk.legacy_encryption import Encryption - from eth_keys import datatypes - - private_key_str = "9822f95dd945e373300f8c8459a831846eda97f314689e01f7cf5b8f1c2298b3" - encrypted_message_str = "0402f48d28d29ae3d681e4cbbe499be0803c2a9d94534d0a4501ab79fd531183fbd837a021c1c117f47737e71c430b9d33915615f68c8dcb5e2f4e4dda4c9415d20a8b5fad9770b14067f2dd31a141a8a8da1f56eb2577715409dbf3c39b9bfa7b90c1acd838fe147c95f0e1ca9359a4cfd52367a73a6d6c548b492faa" - - private_key = datatypes.PrivateKey(bytes.fromhex(private_key_str)) - - encryption = Encryption() - encrypted_message = encryption.decrypt(bytes.fromhex(encrypted_message_str), private_key) - ``` - -#### encrypt(data, public_key, shared_mac_data=b'') - -Encrypt data with ECIES method to the given public key -1) generate r = random value -2) generate shared-secret = kdf( ecdhAgree(r, P) ) -3) generate R = rG [same op as generating a public key] -4) 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag - -* **Parameters:** - * **data** (`bytes`) – Data to be encrypted - * **public_key** (`PublicKey`) – Public to be used to encrypt provided data. - * **shared_mac_data** (`bytes`) – shared mac additional data as suffix. -* **Return type:** - `bytes` -* **Returns:** - Encrypted byte string -* **Example:** - ```python - from human_protocol_sdk.legacy_encryption import Encryption - from eth_keys import datatypes - - public_key_str = "0a1d228684bc8c8c7611df3264f04ebd823651acc46b28b3574d2e69900d5e34f04a26cf13237fa42ab23245b58060c239b356b0a276f57e8de1234c7100fcf9" - - public_key = datatypes.PublicKey(bytes.fromhex(private_key_str)) - - encryption = Encryption() - encrypted_message = encryption.encrypt(b'your message', public_key) - ``` - -#### generate_private_key() - -Generates a new SECP256K1 private key and return it - -* **Return type:** - `PrivateKey` -* **Returns:** - New SECP256K1 private key. -* **Example:** - ```python - from human_protocol_sdk.legacy_encryption import Encryption - - encryption = Encryption() - private_key = encryption.generate_private_key() - ``` - -#### *static* generate_public_key(private_key) - -Generates a public key with combination to private key provided. - -* **Parameters:** - **private_key** (`bytes`) – Private to be used to create public key. -* **Return type:** - `PublicKey` -* **Returns:** - Public key object. -* **Example:** - ```python - from human_protocol_sdk.legacy_encryption import Encryption - - private_key_str = "9822f95dd945e373300f8c8459a831846eda97f314689e01f7cf5b8f1c2298b3" - - public_key = Encryption.generate_public_key(bytes.fromhex(private_key_str)) - ``` - -#### *static* is_encrypted(data) - -Checks whether data is already encrypted by verifying ecies header. - -* **Parameters:** - **data** (`bytes`) – Data to be checked. -* **Return type:** - `bool` -* **Returns:** - True if data is encrypted, False otherwise. -* **Example:** - ```python - from human_protocol_sdk.legacy_encryption import Encryption - - encrypted_message_str = "0402f48d28d29ae3d681e4cbbe499be0803c2a9d94534d0a4501ab79fd531183fbd837a021c1c117f47737e71c430b9d33915615f68c8dcb5e2f4e4dda4c9415d20a8b5fad9770b14067f2dd31a141a8a8da1f56eb2577715409dbf3c39b9bfa7b90c1acd838fe147c95f0e1ca9359a4cfd52367a73a6d6c548b492faa" - - is_encrypted = Encryption.is_encrypted(bytes.fromhex(encrypted_message_str)) - ``` - -### *exception* human_protocol_sdk.legacy_encryption.InvalidPublicKey - -Bases: `Exception` - -A custom exception raised when trying to convert bytes -into an elliptic curve public key. diff --git a/docs/sdk/python/human_protocol_sdk.md b/docs/sdk/python/human_protocol_sdk.md deleted file mode 100644 index 09d67a12cb..0000000000 --- a/docs/sdk/python/human_protocol_sdk.md +++ /dev/null @@ -1,224 +0,0 @@ -# human_protocol_sdk package - -## Subpackages - -* [human_protocol_sdk.agreement package](human_protocol_sdk.agreement.md) - * [Getting Started](human_protocol_sdk.agreement.md#getting-started) - * [A simple example](human_protocol_sdk.agreement.md#a-simple-example) - * [Submodules](human_protocol_sdk.agreement.md#submodules) - * [human_protocol_sdk.agreement.bootstrap module](human_protocol_sdk.agreement.bootstrap.md) - * [`confidence_intervals()`](human_protocol_sdk.agreement.bootstrap.md#human_protocol_sdk.agreement.bootstrap.confidence_intervals) - * [human_protocol_sdk.agreement.measures module](human_protocol_sdk.agreement.measures.md) - * [`agreement()`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.agreement) - * [`cohens_kappa()`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.cohens_kappa) - * [`fleiss_kappa()`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.fleiss_kappa) - * [`krippendorffs_alpha()`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.krippendorffs_alpha) - * [`percentage()`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.percentage) - * [`sigma()`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.sigma) - * [human_protocol_sdk.agreement.utils module](human_protocol_sdk.agreement.utils.md) - * [`NormalDistribution`](human_protocol_sdk.agreement.utils.md#human_protocol_sdk.agreement.utils.NormalDistribution) - * [`confusion_matrix()`](human_protocol_sdk.agreement.utils.md#human_protocol_sdk.agreement.utils.confusion_matrix) - * [`label_counts()`](human_protocol_sdk.agreement.utils.md#human_protocol_sdk.agreement.utils.label_counts) - * [`observed_and_expected_differences()`](human_protocol_sdk.agreement.utils.md#human_protocol_sdk.agreement.utils.observed_and_expected_differences) - * [`records_from_annotations()`](human_protocol_sdk.agreement.utils.md#human_protocol_sdk.agreement.utils.records_from_annotations) -* [human_protocol_sdk.encryption package](human_protocol_sdk.encryption.md) - * [Submodules](human_protocol_sdk.encryption.md#submodules) - * [human_protocol_sdk.encryption.encryption module](human_protocol_sdk.encryption.encryption.md) - * [Code Example](human_protocol_sdk.encryption.encryption.md#code-example) - * [Module](human_protocol_sdk.encryption.encryption.md#module) - * [`Encryption`](human_protocol_sdk.encryption.encryption.md#human_protocol_sdk.encryption.encryption.Encryption) - * [human_protocol_sdk.encryption.encryption_utils module](human_protocol_sdk.encryption.encryption_utils.md) - * [Code Example](human_protocol_sdk.encryption.encryption_utils.md#code-example) - * [Module](human_protocol_sdk.encryption.encryption_utils.md#module) - * [`EncryptionUtils`](human_protocol_sdk.encryption.encryption_utils.md#human_protocol_sdk.encryption.encryption_utils.EncryptionUtils) -* [human_protocol_sdk.escrow package](human_protocol_sdk.escrow.md) - * [Submodules](human_protocol_sdk.escrow.md#submodules) - * [human_protocol_sdk.escrow.escrow_client module](human_protocol_sdk.escrow.escrow_client.md) - * [Code Example](human_protocol_sdk.escrow.escrow_client.md#code-example) - * [Module](human_protocol_sdk.escrow.escrow_client.md#module) - * [`EscrowCancel`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowCancel) - * [`EscrowClient`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClient) - * [`EscrowClientError`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowClientError) - * [`EscrowConfig`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowConfig) - * [`EscrowWithdraw`](human_protocol_sdk.escrow.escrow_client.md#human_protocol_sdk.escrow.escrow_client.EscrowWithdraw) - * [human_protocol_sdk.escrow.escrow_utils module](human_protocol_sdk.escrow.escrow_utils.md) - * [Code Example](human_protocol_sdk.escrow.escrow_utils.md#code-example) - * [Module](human_protocol_sdk.escrow.escrow_utils.md#module) - * [`CancellationRefund`](human_protocol_sdk.escrow.escrow_utils.md#human_protocol_sdk.escrow.escrow_utils.CancellationRefund) - * [`EscrowData`](human_protocol_sdk.escrow.escrow_utils.md#human_protocol_sdk.escrow.escrow_utils.EscrowData) - * [`EscrowUtils`](human_protocol_sdk.escrow.escrow_utils.md#human_protocol_sdk.escrow.escrow_utils.EscrowUtils) - * [`Payout`](human_protocol_sdk.escrow.escrow_utils.md#human_protocol_sdk.escrow.escrow_utils.Payout) - * [`StatusEvent`](human_protocol_sdk.escrow.escrow_utils.md#human_protocol_sdk.escrow.escrow_utils.StatusEvent) -* [human_protocol_sdk.kvstore package](human_protocol_sdk.kvstore.md) - * [Submodules](human_protocol_sdk.kvstore.md#submodules) - * [human_protocol_sdk.kvstore.kvstore_client module](human_protocol_sdk.kvstore.kvstore_client.md) - * [Code Example](human_protocol_sdk.kvstore.kvstore_client.md#code-example) - * [Module](human_protocol_sdk.kvstore.kvstore_client.md#module) - * [`KVStoreClient`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClient) - * [`KVStoreClientError`](human_protocol_sdk.kvstore.kvstore_client.md#human_protocol_sdk.kvstore.kvstore_client.KVStoreClientError) - * [human_protocol_sdk.kvstore.kvstore_utils module](human_protocol_sdk.kvstore.kvstore_utils.md) - * [Code Example](human_protocol_sdk.kvstore.kvstore_utils.md#code-example) - * [Module](human_protocol_sdk.kvstore.kvstore_utils.md#module) - * [`KVStoreData`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreData) - * [`KVStoreUtils`](human_protocol_sdk.kvstore.kvstore_utils.md#human_protocol_sdk.kvstore.kvstore_utils.KVStoreUtils) -* [human_protocol_sdk.operator package](human_protocol_sdk.operator.md) - * [Submodules](human_protocol_sdk.operator.md#submodules) - * [human_protocol_sdk.operator.operator_utils module](human_protocol_sdk.operator.operator_utils.md) - * [Code Example](human_protocol_sdk.operator.operator_utils.md#code-example) - * [Module](human_protocol_sdk.operator.operator_utils.md#module) - * [`OperatorData`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorData) - * [`OperatorFilter`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorFilter) - * [`OperatorUtils`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtils) - * [`OperatorUtilsError`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtilsError) - * [`RewardData`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.RewardData) -* [human_protocol_sdk.staking package](human_protocol_sdk.staking.md) - * [Submodules](human_protocol_sdk.staking.md#submodules) - * [human_protocol_sdk.staking.staking_client module](human_protocol_sdk.staking.staking_client.md) - * [Code Example](human_protocol_sdk.staking.staking_client.md#code-example) - * [Module](human_protocol_sdk.staking.staking_client.md#module) - * [`StakingClient`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient) - * [`StakingClientError`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClientError) - * [human_protocol_sdk.staking.staking_utils module](human_protocol_sdk.staking.staking_utils.md) - * [Code Example](human_protocol_sdk.staking.staking_utils.md#code-example) - * [Module](human_protocol_sdk.staking.staking_utils.md#module) - * [`StakerData`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakerData) - * [`StakingUtils`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakingUtils) - * [`StakingUtilsError`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakingUtilsError) -* [human_protocol_sdk.statistics package](human_protocol_sdk.statistics.md) - * [Submodules](human_protocol_sdk.statistics.md#submodules) - * [human_protocol_sdk.statistics.statistics_client module](human_protocol_sdk.statistics.statistics_client.md) - * [Code Example](human_protocol_sdk.statistics.statistics_client.md#code-example) - * [Module](human_protocol_sdk.statistics.statistics_client.md#module) - * [`DailyEscrowData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyEscrowData) - * [`DailyHMTData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyHMTData) - * [`DailyPaymentData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyPaymentData) - * [`DailyWorkerData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyWorkerData) - * [`EscrowStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.EscrowStatistics) - * [`HMTHolder`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTHolder) - * [`HMTHoldersParam`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTHoldersParam) - * [`HMTStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTStatistics) - * [`PaymentStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.PaymentStatistics) - * [`StatisticsClient`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient) - * [`StatisticsClientError`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClientError) - * [`WorkerStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.WorkerStatistics) -* [human_protocol_sdk.storage package](human_protocol_sdk.storage.md) - * [Submodules](human_protocol_sdk.storage.md#submodules) - * [human_protocol_sdk.storage.storage_client module](human_protocol_sdk.storage.storage_client.md) - * [Code Example](human_protocol_sdk.storage.storage_client.md#code-example) - * [Module](human_protocol_sdk.storage.storage_client.md#module) - * [`Credentials`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.Credentials) - * [`StorageClient`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient) - * [`StorageClientError`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClientError) - * [`StorageFileNotFoundError`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageFileNotFoundError) - * [human_protocol_sdk.storage.storage_utils module](human_protocol_sdk.storage.storage_utils.md) - * [`StorageUtils`](human_protocol_sdk.storage.storage_utils.md#human_protocol_sdk.storage.storage_utils.StorageUtils) -* [human_protocol_sdk.transaction package](human_protocol_sdk.transaction.md) - * [Submodules](human_protocol_sdk.transaction.md#submodules) - * [human_protocol_sdk.transaction.transaction_utils module](human_protocol_sdk.transaction.transaction_utils.md) - * [Code Example](human_protocol_sdk.transaction.transaction_utils.md#code-example) - * [Module](human_protocol_sdk.transaction.transaction_utils.md#module) - * [`InternalTransaction`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.InternalTransaction) - * [`TransactionData`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionData) - * [`TransactionUtils`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtils) - * [`TransactionUtilsError`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtilsError) -* [human_protocol_sdk.worker package](human_protocol_sdk.worker.md) - * [Submodules](human_protocol_sdk.worker.md#submodules) - * [human_protocol_sdk.worker.worker_utils module](human_protocol_sdk.worker.worker_utils.md) - * [`WorkerData`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerData) - * [`WorkerUtils`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerUtils) - * [`WorkerUtilsError`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerUtilsError) - -## Submodules - -* [human_protocol_sdk.constants module](human_protocol_sdk.constants.md) - * [`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId) - * [`ChainId.BSC_MAINNET`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.BSC_MAINNET) - * [`ChainId.BSC_TESTNET`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.BSC_TESTNET) - * [`ChainId.LOCALHOST`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.LOCALHOST) - * [`ChainId.MAINNET`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.MAINNET) - * [`ChainId.POLYGON`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.POLYGON) - * [`ChainId.POLYGON_AMOY`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.POLYGON_AMOY) - * [`ChainId.SEPOLIA`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId.SEPOLIA) - * [`KVStoreKeys`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys) - * [`KVStoreKeys.category`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.category) - * [`KVStoreKeys.fee`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.fee) - * [`KVStoreKeys.job_types`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.job_types) - * [`KVStoreKeys.operator_name`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.operator_name) - * [`KVStoreKeys.public_key`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.public_key) - * [`KVStoreKeys.public_key_hash`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.public_key_hash) - * [`KVStoreKeys.registration_instructions`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.registration_instructions) - * [`KVStoreKeys.registration_needed`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.registration_needed) - * [`KVStoreKeys.role`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.role) - * [`KVStoreKeys.url`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.url) - * [`KVStoreKeys.webhook_url`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.webhook_url) - * [`KVStoreKeys.website`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys.website) - * [`OperatorCategory`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OperatorCategory) - * [`OperatorCategory.MACHINE_LEARNING`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OperatorCategory.MACHINE_LEARNING) - * [`OperatorCategory.MARKET_MAKING`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OperatorCategory.MARKET_MAKING) - * [`OrderDirection`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OrderDirection) - * [`OrderDirection.ASC`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OrderDirection.ASC) - * [`OrderDirection.DESC`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OrderDirection.DESC) - * [`Role`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Role) - * [`Role.exchange_oracle`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Role.exchange_oracle) - * [`Role.job_launcher`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Role.job_launcher) - * [`Role.recording_oracle`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Role.recording_oracle) - * [`Role.reputation_oracle`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Role.reputation_oracle) - * [`Status`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status) - * [`Status.Cancelled`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.Cancelled) - * [`Status.Complete`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.Complete) - * [`Status.Launched`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.Launched) - * [`Status.Paid`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.Paid) - * [`Status.Partial`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.Partial) - * [`Status.Pending`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.Pending) - * [`Status.ToCancel`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status.ToCancel) -* [human_protocol_sdk.filter module](human_protocol_sdk.filter.md) - * [`CancellationRefundFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.CancellationRefundFilter) - * [`CancellationRefundFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.CancellationRefundFilter.__init__) - * [`EscrowFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.EscrowFilter) - * [`EscrowFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.EscrowFilter.__init__) - * [`FilterError`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.FilterError) - * [`PayoutFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.PayoutFilter) - * [`PayoutFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.PayoutFilter.__init__) - * [`StakersFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StakersFilter) - * [`StakersFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StakersFilter.__init__) - * [`StatisticsFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter) - * [`StatisticsFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter.__init__) - * [`StatusEventFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatusEventFilter) - * [`StatusEventFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatusEventFilter.__init__) - * [`TransactionFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.TransactionFilter) - * [`TransactionFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.TransactionFilter.__init__) - * [`WorkerFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.WorkerFilter) - * [`WorkerFilter.__init__()`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.WorkerFilter.__init__) -* [human_protocol_sdk.legacy_encryption module](human_protocol_sdk.legacy_encryption.md) - * [`DecryptionError`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.DecryptionError) - * [`Encryption`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption) - * [`Encryption.CIPHER`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.CIPHER) - * [`Encryption.ELLIPTIC_CURVE`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.ELLIPTIC_CURVE) - * [`Encryption.KEY_LEN`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.KEY_LEN) - * [`Encryption.MODE`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.MODE) - * [`Encryption.PUBLIC_KEY_LEN`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.PUBLIC_KEY_LEN) - * [`Encryption.decrypt()`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.decrypt) - * [`Encryption.encrypt()`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.encrypt) - * [`Encryption.generate_private_key()`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.generate_private_key) - * [`Encryption.generate_public_key()`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.generate_public_key) - * [`Encryption.is_encrypted()`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption.is_encrypted) - * [`InvalidPublicKey`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.InvalidPublicKey) -* [human_protocol_sdk.utils module](human_protocol_sdk.utils.md) - * [`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions) - * [`SubgraphOptions.__init__()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions.__init__) - * [`SubgraphOptions.base_delay`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions.base_delay) - * [`SubgraphOptions.indexer_id`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions.indexer_id) - * [`SubgraphOptions.max_retries`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions.max_retries) - * [`custom_gql_fetch()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.custom_gql_fetch) - * [`get_contract_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_contract_interface) - * [`get_erc20_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_erc20_interface) - * [`get_escrow_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_escrow_interface) - * [`get_factory_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_factory_interface) - * [`get_hmt_balance()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_hmt_balance) - * [`get_kvstore_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_kvstore_interface) - * [`get_staking_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_staking_interface) - * [`handle_error()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.handle_error) - * [`is_indexer_error()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.is_indexer_error) - * [`parse_transfer_transaction()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.parse_transfer_transaction) - * [`validate_json()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.validate_json) - * [`validate_url()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.validate_url) diff --git a/docs/sdk/python/human_protocol_sdk.operator.md b/docs/sdk/python/human_protocol_sdk.operator.md deleted file mode 100644 index 7dd40a95c2..0000000000 --- a/docs/sdk/python/human_protocol_sdk.operator.md +++ /dev/null @@ -1,22 +0,0 @@ -# human_protocol_sdk.operator package - -This module enables to perform actions on staking contracts and -obtain staking information from both the contracts and subgraph. - -## Submodules - -* [human_protocol_sdk.operator.operator_utils module](human_protocol_sdk.operator.operator_utils.md) - * [Code Example](human_protocol_sdk.operator.operator_utils.md#code-example) - * [Module](human_protocol_sdk.operator.operator_utils.md#module) - * [`OperatorData`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorData) - * [`OperatorData.__init__()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorData.__init__) - * [`OperatorFilter`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorFilter) - * [`OperatorFilter.__init__()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorFilter.__init__) - * [`OperatorUtils`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtils) - * [`OperatorUtils.get_operator()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtils.get_operator) - * [`OperatorUtils.get_operators()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtils.get_operators) - * [`OperatorUtils.get_reputation_network_operators()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtils.get_reputation_network_operators) - * [`OperatorUtils.get_rewards_info()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtils.get_rewards_info) - * [`OperatorUtilsError`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.OperatorUtilsError) - * [`RewardData`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.RewardData) - * [`RewardData.__init__()`](human_protocol_sdk.operator.operator_utils.md#human_protocol_sdk.operator.operator_utils.RewardData.__init__) diff --git a/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md b/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md deleted file mode 100644 index 8a1a1cab2c..0000000000 --- a/docs/sdk/python/human_protocol_sdk.operator.operator_utils.md +++ /dev/null @@ -1,188 +0,0 @@ -# human_protocol_sdk.operator.operator_utils module - -Utility class for operator-related operations. - -## Code Example - -```python -from human_protocol_sdk.constants import ChainId -from human_protocol_sdk.operator import OperatorUtils, OperatorFilter - -print( - OperatorUtils.get_operators( - OperatorFilter(chain_id=ChainId.POLYGON_AMOY, roles=["Job Launcher"]) - ) -) -``` - -## Module - -### *class* human_protocol_sdk.operator.operator_utils.OperatorData(chain_id, id, address, amount_jobs_processed, reputation_networks, staked_amount=None, locked_amount=None, locked_until_timestamp=None, withdrawn_amount=None, slashed_amount=None, role=None, fee=None, public_key=None, webhook_url=None, website=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, name=None, category=None) - -Bases: `object` - -#### \_\_init_\_(chain_id, id, address, amount_jobs_processed, reputation_networks, staked_amount=None, locked_amount=None, locked_until_timestamp=None, withdrawn_amount=None, slashed_amount=None, role=None, fee=None, public_key=None, webhook_url=None, website=None, url=None, job_types=None, registration_needed=None, registration_instructions=None, name=None, category=None) - -Initializes a OperatorData instance. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Chain Identifier - * **id** (`str`) – Identifier - * **address** (`str`) – Address - * **staked_amount** (`Optional`[`str`]) – Amount staked - * **locked_amount** (`Optional`[`str`]) – Amount locked - * **locked_until_timestamp** (`Optional`[`str`]) – Locked until timestamp - * **withdrawn_amount** (`Optional`[`str`]) – Amount withdrawn - * **slashed_amount** (`Optional`[`str`]) – Amount slashed - * **amount_jobs_processed** (`str`) – Amount of jobs launched - * **role** (`Optional`[`str`]) – Role - * **fee** (`Optional`[`str`]) – Fee - * **public_key** (`Optional`[`str`]) – Public key - * **webhook_url** (`Optional`[`str`]) – Webhook URL - * **website** (`Optional`[`str`]) – Website URL - * **url** (`Optional`[`str`]) – URL - * **job_types** (`Union`[`List`[`str`], `str`, `None`]) – Job types - * **registration_needed** (`Optional`[`bool`]) – Whether registration is needed - * **registration_instructions** (`Optional`[`str`]) – Registration instructions - * **reputation_networks** (`Union`[`List`[`str`], `str`]) – List of reputation networks - * **name** (`Optional`[`str`]) – Name - * **category** (`Optional`[`str`]) – Category - -### *class* human_protocol_sdk.operator.operator_utils.OperatorFilter(chain_id, roles=[], min_staked_amount=None, order_by=None, order_direction=OrderDirection.DESC, first=10, skip=0) - -Bases: `object` - -A class used to filter operators. - -#### \_\_init_\_(chain_id, roles=[], min_staked_amount=None, order_by=None, order_direction=OrderDirection.DESC, first=10, skip=0) - -Initializes a OperatorFilter instance. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Chain ID to request data - * **roles** (`Optional`[`str`]) – Roles to filter by - * **min_staked_amount** (`Optional`[`int`]) – Minimum amount staked to filter by - * **order_by** (`Optional`[`str`]) – Property to order by, e.g., “role” - * **order_direction** ([`OrderDirection`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OrderDirection)) – Order direction of results, “asc” or “desc” - * **first** (`int`) – Number of items per page - * **skip** (`int`) – Number of items to skip (for pagination) - -### *class* human_protocol_sdk.operator.operator_utils.OperatorUtils - -Bases: `object` - -A utility class that provides additional operator-related functionalities. - -#### *static* get_operator(chain_id, operator_address, options=None) - -Gets the operator details. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Network in which the operator exists - * **operator_address** (`str`) – Address of the operator - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `Optional`[[`OperatorData`](#human_protocol_sdk.operator.operator_utils.OperatorData)] -* **Returns:** - Operator data if exists, otherwise None -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils - - chain_id = ChainId.POLYGON_AMOY - operator_address = '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - - operator_data = OperatorUtils.get_operator(chain_id, operator_address) - print(operator_data) - ``` - -#### *static* get_operators(filter, options=None) - -Get operators data of the protocol. - -* **Parameters:** - * **filter** ([`OperatorFilter`](#human_protocol_sdk.operator.operator_utils.OperatorFilter)) – Operator filter - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`OperatorData`](#human_protocol_sdk.operator.operator_utils.OperatorData)] -* **Returns:** - List of operators data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils, OperatorFilter - - print( - OperatorUtils.get_operators( - OperatorFilter(chain_id=ChainId.POLYGON_AMOY, roles=["Job Launcher"]) - ) - ) - ``` - -#### *static* get_reputation_network_operators(chain_id, address, role=None, options=None) - -Get the reputation network operators of the specified address. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Network in which the reputation network exists - * **address** (`str`) – Address of the reputation oracle - * **role** (`Optional`[`str`]) – (Optional) Role of the operator - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`OperatorData`](#human_protocol_sdk.operator.operator_utils.OperatorData)] -* **Returns:** - Returns an array of operator details -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils - - operators = OperatorUtils.get_reputation_network_operators( - ChainId.POLYGON_AMOY, - '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - ) - print(operators) - ``` - -#### *static* get_rewards_info(chain_id, slasher, options=None) - -Get rewards of the given slasher. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Network in which the slasher exists - * **slasher** (`str`) – Address of the slasher - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`RewardData`](#human_protocol_sdk.operator.operator_utils.RewardData)] -* **Returns:** - List of rewards info -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils - - rewards_info = OperatorUtils.get_rewards_info( - ChainId.POLYGON_AMOY, - '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - ) - print(rewards_info) - ``` - -### *exception* human_protocol_sdk.operator.operator_utils.OperatorUtilsError - -Bases: `Exception` - -Raised when an error occurs while interacting with the operator. - -### *class* human_protocol_sdk.operator.operator_utils.RewardData(escrow_address, amount) - -Bases: `object` - -#### \_\_init_\_(escrow_address, amount) - -Initializes a RewardData instance. - -* **Parameters:** - * **escrow_address** (`str`) – Escrow address - * **amount** (`int`) – Amount diff --git a/docs/sdk/python/human_protocol_sdk.staking.md b/docs/sdk/python/human_protocol_sdk.staking.md deleted file mode 100644 index 04a5aea76f..0000000000 --- a/docs/sdk/python/human_protocol_sdk.staking.md +++ /dev/null @@ -1,28 +0,0 @@ -# human_protocol_sdk.staking package - -This module enables to perform actions on staking contracts and -obtain staking information from both the contracts and subgraph. - -## Submodules - -* [human_protocol_sdk.staking.staking_client module](human_protocol_sdk.staking.staking_client.md) - * [Code Example](human_protocol_sdk.staking.staking_client.md#code-example) - * [Module](human_protocol_sdk.staking.staking_client.md#module) - * [`StakingClient`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient) - * [`StakingClient.__init__()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.__init__) - * [`StakingClient.approve_stake()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.approve_stake) - * [`StakingClient.get_staker_info()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.get_staker_info) - * [`StakingClient.slash()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.slash) - * [`StakingClient.stake()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.stake) - * [`StakingClient.unstake()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.unstake) - * [`StakingClient.withdraw()`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClient.withdraw) - * [`StakingClientError`](human_protocol_sdk.staking.staking_client.md#human_protocol_sdk.staking.staking_client.StakingClientError) -* [human_protocol_sdk.staking.staking_utils module](human_protocol_sdk.staking.staking_utils.md) - * [Code Example](human_protocol_sdk.staking.staking_utils.md#code-example) - * [Module](human_protocol_sdk.staking.staking_utils.md#module) - * [`StakerData`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakerData) - * [`StakerData.__init__()`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakerData.__init__) - * [`StakingUtils`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakingUtils) - * [`StakingUtils.get_staker()`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakingUtils.get_staker) - * [`StakingUtils.get_stakers()`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakingUtils.get_stakers) - * [`StakingUtilsError`](human_protocol_sdk.staking.staking_utils.md#human_protocol_sdk.staking.staking_utils.StakingUtilsError) diff --git a/docs/sdk/python/human_protocol_sdk.staking.staking_client.md b/docs/sdk/python/human_protocol_sdk.staking.staking_client.md deleted file mode 100644 index c0155d7cb5..0000000000 --- a/docs/sdk/python/human_protocol_sdk.staking.staking_client.md +++ /dev/null @@ -1,106 +0,0 @@ -# human_protocol_sdk.staking.staking_client module - -This client enables performing actions on staking contracts and -obtaining staking information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the web3. -To use this client, you need to create a Web3 instance and configure the default account, -as well as some middlewares. - -## Code Example - -* With Signer - -```python -from eth_typing import URI -from web3 import Web3 -from web3.middleware import SignAndSendRawMiddlewareBuilder -from web3.providers.auto import load_provider_from_uri - -from human_protocol_sdk.staking import StakingClient - -def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - -(w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') -staking_client = StakingClient(w3) -``` - -* Without Signer (For read operations only) - -```python -from eth_typing import URI -from web3 import Web3 -from web3.providers.auto import load_provider_from_uri - -from human_protocol_sdk.staking import StakingClient - -w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) -staking_client = StakingClient(w3) -``` - -## Module - -### *class* human_protocol_sdk.staking.staking_client.StakingClient(w3) - -Bases: `object` - -A class used to manage staking on the HUMAN network. - -#### \_\_init_\_(w3) - -Initializes a Staking instance - -* **Parameters:** - **w3** (`Web3`) – Web3 instance - -#### approve_stake(\*args, \*\*kwargs) - -#### get_staker_info(staker_address) - -Retrieves comprehensive staking information for a staker. - -* **Parameters:** - **staker_address** (`str`) – The address of the staker -* **Return type:** - `dict` -* **Returns:** - A dictionary containing staker information -* **Validate:** - - Staker address must be valid -* **Example:** - ```python - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - staking_client = StakingClient(w3) - - staking_info = staking_client.get_staker_info('0xYourStakerAddress') - print(staking_info['stakedAmount']) - ``` - -#### slash(\*args, \*\*kwargs) - -#### stake(\*args, \*\*kwargs) - -#### unstake(\*args, \*\*kwargs) - -#### withdraw(\*args, \*\*kwargs) - -### *exception* human_protocol_sdk.staking.staking_client.StakingClientError - -Bases: `Exception` - -Raises when some error happens when interacting with staking. diff --git a/docs/sdk/python/human_protocol_sdk.staking.staking_utils.md b/docs/sdk/python/human_protocol_sdk.staking.staking_utils.md deleted file mode 100644 index 86d2a79482..0000000000 --- a/docs/sdk/python/human_protocol_sdk.staking.staking_utils.md +++ /dev/null @@ -1,49 +0,0 @@ -# human_protocol_sdk.staking.staking_utils module - -Utility class for staking-related operations. - -## Code Example - -```python -from human_protocol_sdk.constants import ChainId -from human_protocol_sdk.staking.staking_utils import StakingUtils, StakersFilter - -stakers = StakingUtils.get_stakers( - StakersFilter( - chain_id=ChainId.POLYGON_AMOY, - min_staked_amount="1000000000000000000", - max_locked_amount="5000000000000000000", - order_by="withdrawnAmount", - order_direction="asc", - first=5, - skip=0, - ) -) -print("Filtered stakers:", stakers) -``` - -## Module - -### *class* human_protocol_sdk.staking.staking_utils.StakerData(id, address, staked_amount, locked_amount, withdrawn_amount, slashed_amount, locked_until_timestamp, last_deposit_timestamp) - -Bases: `object` - -#### \_\_init_\_(id, address, staked_amount, locked_amount, withdrawn_amount, slashed_amount, locked_until_timestamp, last_deposit_timestamp) - -### *class* human_protocol_sdk.staking.staking_utils.StakingUtils - -Bases: `object` - -#### *static* get_staker(chain_id, address, options=None) - -* **Return type:** - `Optional`[[`StakerData`](#human_protocol_sdk.staking.staking_utils.StakerData)] - -#### *static* get_stakers(filter, options=None) - -* **Return type:** - `List`[[`StakerData`](#human_protocol_sdk.staking.staking_utils.StakerData)] - -### *exception* human_protocol_sdk.staking.staking_utils.StakingUtilsError - -Bases: `Exception` diff --git a/docs/sdk/python/human_protocol_sdk.statistics.md b/docs/sdk/python/human_protocol_sdk.statistics.md deleted file mode 100644 index ee37413d17..0000000000 --- a/docs/sdk/python/human_protocol_sdk.statistics.md +++ /dev/null @@ -1,38 +0,0 @@ -# human_protocol_sdk.statistics package - -This module allows to read statistical data from the subgraph. - -## Submodules - -* [human_protocol_sdk.statistics.statistics_client module](human_protocol_sdk.statistics.statistics_client.md) - * [Code Example](human_protocol_sdk.statistics.statistics_client.md#code-example) - * [Module](human_protocol_sdk.statistics.statistics_client.md#module) - * [`DailyEscrowData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyEscrowData) - * [`DailyEscrowData.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyEscrowData.__init__) - * [`DailyHMTData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyHMTData) - * [`DailyHMTData.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyHMTData.__init__) - * [`DailyPaymentData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyPaymentData) - * [`DailyPaymentData.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyPaymentData.__init__) - * [`DailyWorkerData`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyWorkerData) - * [`DailyWorkerData.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.DailyWorkerData.__init__) - * [`EscrowStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.EscrowStatistics) - * [`EscrowStatistics.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.EscrowStatistics.__init__) - * [`HMTHolder`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTHolder) - * [`HMTHolder.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTHolder.__init__) - * [`HMTHoldersParam`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTHoldersParam) - * [`HMTHoldersParam.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTHoldersParam.__init__) - * [`HMTStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTStatistics) - * [`HMTStatistics.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.HMTStatistics.__init__) - * [`PaymentStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.PaymentStatistics) - * [`PaymentStatistics.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.PaymentStatistics.__init__) - * [`StatisticsClient`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient) - * [`StatisticsClient.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.__init__) - * [`StatisticsClient.get_escrow_statistics()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.get_escrow_statistics) - * [`StatisticsClient.get_hmt_daily_data()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.get_hmt_daily_data) - * [`StatisticsClient.get_hmt_holders()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.get_hmt_holders) - * [`StatisticsClient.get_hmt_statistics()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.get_hmt_statistics) - * [`StatisticsClient.get_payment_statistics()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.get_payment_statistics) - * [`StatisticsClient.get_worker_statistics()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClient.get_worker_statistics) - * [`StatisticsClientError`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.StatisticsClientError) - * [`WorkerStatistics`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.WorkerStatistics) - * [`WorkerStatistics.__init__()`](human_protocol_sdk.statistics.statistics_client.md#human_protocol_sdk.statistics.statistics_client.WorkerStatistics.__init__) diff --git a/docs/sdk/python/human_protocol_sdk.statistics.statistics_client.md b/docs/sdk/python/human_protocol_sdk.statistics.statistics_client.md deleted file mode 100644 index 5d7b6396c0..0000000000 --- a/docs/sdk/python/human_protocol_sdk.statistics.statistics_client.md +++ /dev/null @@ -1,349 +0,0 @@ -# human_protocol_sdk.statistics.statistics_client module - -This client enables to obtain statistical information from the subgraph. - -## Code Example - -```python -from human_protocol_sdk.constants import ChainId -from human_protocol_sdk.statistics import StatisticsClient - -statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) -``` - -## Module - -### *class* human_protocol_sdk.statistics.statistics_client.DailyEscrowData(timestamp, escrows_total, escrows_pending, escrows_solved, escrows_paid, escrows_cancelled) - -Bases: `object` - -A class used to specify daily escrow data. - -#### \_\_init_\_(timestamp, escrows_total, escrows_pending, escrows_solved, escrows_paid, escrows_cancelled) - -Initializes a DailyEscrowData instance. - -* **Parameters:** - * **timestamp** (`datetime`) – Timestamp - * **escrows_total** (`int`) – Total escrows - * **escrows_pending** (`int`) – Pending escrows - * **escrows_solved** (`int`) – Solved escrows - * **escrows_paid** (`int`) – Paid escrows - * **escrows_cancelled** (`int`) – Cancelled escrows - -### *class* human_protocol_sdk.statistics.statistics_client.DailyHMTData(timestamp, total_transaction_amount, total_transaction_count, daily_unique_senders, daily_unique_receivers) - -Bases: `object` - -A class used to specify daily HMT data. - -#### \_\_init_\_(timestamp, total_transaction_amount, total_transaction_count, daily_unique_senders, daily_unique_receivers) - -Initializes a DailyHMTData instance. - -* **Parameters:** - * **timestamp** (`datetime`) – Timestamp - * **total_transaction_amount** (`int`) – Total transaction amount - * **total_transaction_count** (`int`) – Total transaction count - * **daily_unique_senders** (`int`) – Total unique senders - * **daily_unique_receivers** (`int`) – Total unique receivers - -### *class* human_protocol_sdk.statistics.statistics_client.DailyPaymentData(timestamp, total_amount_paid, total_count, average_amount_per_worker) - -Bases: `object` - -A class used to specify daily payment data. - -#### \_\_init_\_(timestamp, total_amount_paid, total_count, average_amount_per_worker) - -Initializes a DailyPaymentData instance. - -* **Parameters:** - * **timestamp** (`datetime`) – Timestamp - * **total_amount_paid** (`int`) – Total amount paid - * **total_count** (`int`) – Total count - * **average_amount_per_worker** (`int`) – Average amount per worker - -### *class* human_protocol_sdk.statistics.statistics_client.DailyWorkerData(timestamp, active_workers) - -Bases: `object` - -A class used to specify daily worker data. - -#### \_\_init_\_(timestamp, active_workers) - -Initializes a DailyWorkerData instance. - -* **Parameters:** - * **timestamp** (`datetime`) – Timestamp - * **active_workers** (`int`) – Active workers - -### *class* human_protocol_sdk.statistics.statistics_client.EscrowStatistics(total_escrows, daily_escrows_data) - -Bases: `object` - -A class used to specify escrow statistics. - -#### \_\_init_\_(total_escrows, daily_escrows_data) - -Initializes a EscrowStatistics instance. - -* **Parameters:** - * **total_escrows** (`int`) – Total escrows - * **daily_escrows_data** (`List`[[`DailyEscrowData`](#human_protocol_sdk.statistics.statistics_client.DailyEscrowData)]) – Daily escrows data - -### *class* human_protocol_sdk.statistics.statistics_client.HMTHolder(address, balance) - -Bases: `object` - -A class used to specify HMT holder. - -#### \_\_init_\_(address, balance) - -Initializes a HMTHolder instance. - -* **Parameters:** - * **address** (`str`) – Holder address - * **balance** (`int`) – Holder balance - -### *class* human_protocol_sdk.statistics.statistics_client.HMTHoldersParam(address=None, order_direction='asc') - -Bases: `object` - -A class used to specify parameters for querying HMT holders. - -#### \_\_init_\_(address=None, order_direction='asc') - -Initializes a HMTHoldersParam instance. - -* **Parameters:** - * **address** (`Optional`[`str`]) – Filter by holder’s address - * **order_direction** (`str`) – Optional. Direction of sorting (‘asc’ for ascending, ‘desc’ for descending) - -### *class* human_protocol_sdk.statistics.statistics_client.HMTStatistics(total_transfer_amount, total_transfer_count, total_holders) - -Bases: `object` - -A class used to specify HMT statistics. - -#### \_\_init_\_(total_transfer_amount, total_transfer_count, total_holders) - -Initializes a HMTStatistics instance. - -* **Parameters:** - * **total_transfer_amount** (`int`) – Total transfer amount - * **total_transfer_count** (`int`) – Total transfer count - * **total_holders** (`int`) – Total holders - -### *class* human_protocol_sdk.statistics.statistics_client.PaymentStatistics(daily_payments_data) - -Bases: `object` - -A class used to specify payment statistics. - -#### \_\_init_\_(daily_payments_data) - -Initializes a PaymentStatistics instance. - -* **Parameters:** - **daily_payments_data** (`List`[[`DailyPaymentData`](#human_protocol_sdk.statistics.statistics_client.DailyPaymentData)]) – Daily payments data - -### *class* human_protocol_sdk.statistics.statistics_client.StatisticsClient(chain_id=ChainId.POLYGON_AMOY) - -Bases: `object` - -A client used to get statistical data. - -#### \_\_init_\_(chain_id=ChainId.POLYGON_AMOY) - -Initializes a Statistics instance - -* **Parameters:** - **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Chain ID to get statistical data from - -#### get_escrow_statistics(filter=, options=None) - -Get escrow statistics data for the given date range. - -* **Parameters:** - * **filter** ([`StatisticsFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter)) – Object containing the date range - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - [`EscrowStatistics`](#human_protocol_sdk.statistics.statistics_client.EscrowStatistics) -* **Returns:** - Escrow statistics data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - from human_protocol_sdk.filter import StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_escrow_statistics()) - print( - statistics_client.get_escrow_statistics( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - ``` - -#### get_hmt_daily_data(filter=, options=None) - -Get HMT daily statistics data for the given date range. - -* **Parameters:** - * **filter** ([`StatisticsFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter)) – Object containing the date range - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`DailyHMTData`](#human_protocol_sdk.statistics.statistics_client.DailyHMTData)] -* **Returns:** - HMT statistics data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient, StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_hmt_daily_data()) - print( - statistics_client.get_hmt_daily_data( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - ``` - -#### get_hmt_holders(param=, options=None) - -Get HMT holders data with optional filters and ordering. - -* **Parameters:** - * **param** ([`HMTHoldersParam`](#human_protocol_sdk.statistics.statistics_client.HMTHoldersParam)) – Object containing filter and order parameters - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`HMTHolder`](#human_protocol_sdk.statistics.statistics_client.HMTHolder)] -* **Returns:** - List of HMT holders -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient, HMTHoldersParam - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_hmt_holders()) - print( - statistics_client.get_hmt_holders( - HMTHoldersParam( - address="0x123...", - order_direction="asc", - ) - ) - ) - ``` - -#### get_hmt_statistics(options=None) - -Get HMT statistics data. - -* **Parameters:** - **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - [`HMTStatistics`](#human_protocol_sdk.statistics.statistics_client.HMTStatistics) -* **Returns:** - HMT statistics data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_hmt_statistics()) - ``` - -#### get_payment_statistics(filter=, options=None) - -Get payment statistics data for the given date range. - -* **Parameters:** - * **filter** ([`StatisticsFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter)) – Object containing the date range - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - [`PaymentStatistics`](#human_protocol_sdk.statistics.statistics_client.PaymentStatistics) -* **Returns:** - Payment statistics data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - from human_protocol_sdk.filter import StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_payment_statistics()) - print( - statistics_client.get_payment_statistics( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - ``` - -#### get_worker_statistics(filter=, options=None) - -Get worker statistics data for the given date range. - -* **Parameters:** - * **filter** ([`StatisticsFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter)) – Object containing the date range - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - [`WorkerStatistics`](#human_protocol_sdk.statistics.statistics_client.WorkerStatistics) -* **Returns:** - Worker statistics data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - from human_protocol_sdk.filter import StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_worker_statistics()) - print( - statistics_client.get_worker_statistics( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - ``` - -### *exception* human_protocol_sdk.statistics.statistics_client.StatisticsClientError - -Bases: `Exception` - -Raises when some error happens when getting data from subgraph. - -### *class* human_protocol_sdk.statistics.statistics_client.WorkerStatistics(daily_workers_data) - -Bases: `object` - -A class used to specify worker statistics. - -#### \_\_init_\_(daily_workers_data) - -Initializes a WorkerStatistics instance. - -* **Parameters:** - **daily_workers_data** (`List`[[`DailyWorkerData`](#human_protocol_sdk.statistics.statistics_client.DailyWorkerData)]) – Daily workers data diff --git a/docs/sdk/python/human_protocol_sdk.storage.md b/docs/sdk/python/human_protocol_sdk.storage.md deleted file mode 100644 index 039bef73dd..0000000000 --- a/docs/sdk/python/human_protocol_sdk.storage.md +++ /dev/null @@ -1,22 +0,0 @@ -# human_protocol_sdk.storage package - -This modules contains an s3 client and utilities for files sharing. - -## Submodules - -* [human_protocol_sdk.storage.storage_client module](human_protocol_sdk.storage.storage_client.md) - * [Code Example](human_protocol_sdk.storage.storage_client.md#code-example) - * [Module](human_protocol_sdk.storage.storage_client.md#module) - * [`Credentials`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.Credentials) - * [`Credentials.__init__()`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.Credentials.__init__) - * [`StorageClient`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient) - * [`StorageClient.__init__()`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient.__init__) - * [`StorageClient.bucket_exists()`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient.bucket_exists) - * [`StorageClient.download_files()`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient.download_files) - * [`StorageClient.list_objects()`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient.list_objects) - * [`StorageClient.upload_files()`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClient.upload_files) - * [`StorageClientError`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClientError) - * [`StorageFileNotFoundError`](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageFileNotFoundError) -* [human_protocol_sdk.storage.storage_utils module](human_protocol_sdk.storage.storage_utils.md) - * [`StorageUtils`](human_protocol_sdk.storage.storage_utils.md#human_protocol_sdk.storage.storage_utils.StorageUtils) - * [`StorageUtils.download_file_from_url()`](human_protocol_sdk.storage.storage_utils.md#human_protocol_sdk.storage.storage_utils.StorageUtils.download_file_from_url) diff --git a/docs/sdk/python/human_protocol_sdk.storage.storage_client.md b/docs/sdk/python/human_protocol_sdk.storage.storage_client.md deleted file mode 100644 index e93da074af..0000000000 --- a/docs/sdk/python/human_protocol_sdk.storage.storage_client.md +++ /dev/null @@ -1,246 +0,0 @@ -# human_protocol_sdk.storage.storage_client module - -This client enables to interact with S3 cloud storage services like Amazon S3 Bucket, -Google Cloud Storage and others. - -If credentials are not provided, anonymous access will be used (for downloading files). - -## Code Example - -```python -from human_protocol_sdk.storage import ( - Credentials, - StorageClient, -) - -credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", -) - -storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, -) -``` - -## Module - -### *class* human_protocol_sdk.storage.storage_client.Credentials(access_key, secret_key) - -Bases: `object` - -A class to represent the credentials required to authenticate with an S3-compatible service. - -Example: - -```default -credentials = Credentials( - access_key='my-access-key', - secret_key='my-secret-key' -) -``` - -#### \_\_init_\_(access_key, secret_key) - -Initializes a Credentials instance. - -* **Parameters:** - * **access_key** (`str`) – The access key for the S3-compatible service. - * **secret_key** (`str`) – The secret key for the S3-compatible service. - -### *class* human_protocol_sdk.storage.storage_client.StorageClient(endpoint_url, region=None, credentials=None, secure=True) - -Bases: `object` - -A class for downloading files from an S3-compatible service. - -* **Attribute:** - - client (Minio): The S3-compatible client used for interacting with the service. -* **Example:** - ```python - # Download a list of files from an S3-compatible service - client = StorageClient( - endpoint_url='https://s3.us-west-2.amazonaws.com', - region='us-west-2', - credentials=Credentials( - access_key='my-access-key', - secret_key='my-secret-key' - ) - ) - files = ['file1.txt', 'file2.txt'] - bucket = 'my-bucket' - result_files = client.download_files(files=files, bucket=bucket) - ``` - -#### \_\_init_\_(endpoint_url, region=None, credentials=None, secure=True) - -Initializes the StorageClient with the given endpoint_url, region, and credentials. - -If credentials are not provided, anonymous access will be used. - -* **Parameters:** - * **endpoint_url** (`str`) – The URL of the S3-compatible service. - * **region** (`Optional`[`str`]) – The region of the S3-compatible service. Defaults to None. - * **credentials** (`Optional`[[`Credentials`](#human_protocol_sdk.storage.storage_client.Credentials)]) – The credentials required to authenticate with the S3-compatible service. - Defaults to None for anonymous access. - * **secure** (`Optional`[`bool`]) – Flag to indicate to use secure (TLS) connection to S3 service or not. - Defaults to True. - -#### bucket_exists(bucket) - -Check if a given bucket exists. - -* **Parameters:** - **bucket** (`str`) – The name of the bucket to check. -* **Return type:** - `bool` -* **Returns:** - True if the bucket exists, False otherwise. -* **Raises:** - [**StorageClientError**](#human_protocol_sdk.storage.storage_client.StorageClientError) – If an error occurs while checking the bucket. -* **Example:** - ```python - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - is_exists = storage_client.bucket_exists( - bucket = "my-bucket" - ) - ``` - -#### download_files(files, bucket) - -Downloads a list of files from the specified S3-compatible bucket. - -* **Parameters:** - * **files** (`List`[`str`]) – A list of file keys to download. - * **bucket** (`str`) – The name of the S3-compatible bucket to download from. -* **Return type:** - `List`[`bytes`] -* **Returns:** - A list of file contents (bytes) downloaded from the bucket. -* **Raises:** - * [**StorageClientError**](#human_protocol_sdk.storage.storage_client.StorageClientError) – If an error occurs while downloading the files. - * [**StorageFileNotFoundError**](#human_protocol_sdk.storage.storage_client.StorageFileNotFoundError) – If one of the specified files is not found in the bucket. -* **Example:** - ```python - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - result = storage_client.download_files( - files = ["file1.txt", "file2.txt"], - bucket = "my-bucket" - ) - ``` - -#### list_objects(bucket) - -Return a list of all objects in a given bucket. - -* **Parameters:** - **bucket** (`str`) – The name of the bucket to list objects from. -* **Return type:** - `List`[`str`] -* **Returns:** - A list of object keys in the given bucket. -* **Raises:** - [**StorageClientError**](#human_protocol_sdk.storage.storage_client.StorageClientError) – If an error occurs while listing the objects. -* **Example:** - ```python - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - result = storage_client.list_objects( - bucket = "my-bucket" - ) - ``` - -#### upload_files(files, bucket) - -Uploads a list of files to the specified S3-compatible bucket. - -* **Parameters:** - * **files** (`List`[`dict`]) – A list of files to upload. - * **bucket** (`str`) – The name of the S3-compatible bucket to upload to. -* **Return type:** - `List`[`dict`] -* **Returns:** - List of dict with key, url, hash fields -* **Raises:** - [**StorageClientError**](#human_protocol_sdk.storage.storage_client.StorageClientError) – If an error occurs while uploading the files. -* **Example:** - ```python - from human_protocol_sdk.storage import ( - Credentials, - StorageClient, - ) - - credentials = Credentials( - access_key="my-access-key", - secret_key="my-secret-key", - ) - - storage_client = StorageClient( - endpoint_url="s3.us-west-2.amazonaws.com", - region="us-west-2", - credentials=credentials, - ) - - result = storage_client.upload_files( - files = [{"file": "file content", "key": "file1.txt", "hash": "hash1"}], - bucket = "my-bucket" - ) - ``` - -### *exception* human_protocol_sdk.storage.storage_client.StorageClientError - -Bases: `Exception` - -Raises when some error happens when interacting with storage. - -### *exception* human_protocol_sdk.storage.storage_client.StorageFileNotFoundError - -Bases: [`StorageClientError`](#human_protocol_sdk.storage.storage_client.StorageClientError) - -Raises when some error happens when file is not found by its key. diff --git a/docs/sdk/python/human_protocol_sdk.storage.storage_utils.md b/docs/sdk/python/human_protocol_sdk.storage.storage_utils.md deleted file mode 100644 index 8b08a80370..0000000000 --- a/docs/sdk/python/human_protocol_sdk.storage.storage_utils.md +++ /dev/null @@ -1,30 +0,0 @@ -# human_protocol_sdk.storage.storage_utils module - -Utility class for storage-related operations. - -### *class* human_protocol_sdk.storage.storage_utils.StorageUtils - -Bases: `object` - -Utility class for storage-related operations. - -#### *static* download_file_from_url(url) - -Downloads a file from the specified URL. - -* **Parameters:** - **url** (`str`) – The URL of the file to download. -* **Return type:** - `bytes` -* **Returns:** - The content of the downloaded file. -* **Raises:** - [**StorageClientError**](human_protocol_sdk.storage.storage_client.md#human_protocol_sdk.storage.storage_client.StorageClientError) – If an error occurs while downloading the file. -* **Example:** - ```python - from human_protocol_sdk.storage import StorageUtils - - result = StorageUtils.download_file_from_url( - "https://www.example.com/file.txt" - ) - ``` diff --git a/docs/sdk/python/human_protocol_sdk.transaction.md b/docs/sdk/python/human_protocol_sdk.transaction.md deleted file mode 100644 index e9e877208c..0000000000 --- a/docs/sdk/python/human_protocol_sdk.transaction.md +++ /dev/null @@ -1,18 +0,0 @@ -# human_protocol_sdk.transaction package - -This module enables to obtain transaction information from -both the contracts and subgraph. - -## Submodules - -* [human_protocol_sdk.transaction.transaction_utils module](human_protocol_sdk.transaction.transaction_utils.md) - * [Code Example](human_protocol_sdk.transaction.transaction_utils.md#code-example) - * [Module](human_protocol_sdk.transaction.transaction_utils.md#module) - * [`InternalTransaction`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.InternalTransaction) - * [`InternalTransaction.__init__()`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.InternalTransaction.__init__) - * [`TransactionData`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionData) - * [`TransactionData.__init__()`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionData.__init__) - * [`TransactionUtils`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtils) - * [`TransactionUtils.get_transaction()`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtils.get_transaction) - * [`TransactionUtils.get_transactions()`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtils.get_transactions) - * [`TransactionUtilsError`](human_protocol_sdk.transaction.transaction_utils.md#human_protocol_sdk.transaction.transaction_utils.TransactionUtilsError) diff --git a/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md b/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md deleted file mode 100644 index e2138632d9..0000000000 --- a/docs/sdk/python/human_protocol_sdk.transaction.transaction_utils.md +++ /dev/null @@ -1,105 +0,0 @@ -# human_protocol_sdk.transaction.transaction_utils module - -Utility class for transaction-related operations. - -## Code Example - -```python -from human_protocol_sdk.constants import ChainId -from human_protocol_sdk.transaction import TransactionUtils, TransactionFilter - -print( - TransactionUtils.get_transactions( - TransactionFilter( - chain_id=ChainId.POLYGON_AMOY, - from_address="0x1234567890123456789012345678901234567890", - to_address="0x0987654321098765432109876543210987654321", - start_date=datetime.datetime(2023, 5, 8), - end_date=datetime.datetime(2023, 6, 8), - ) - ) -) -``` - -## Module - -### *class* human_protocol_sdk.transaction.transaction_utils.InternalTransaction(from_address, to_address, value, method, receiver, escrow, token) - -Bases: `object` - -#### \_\_init_\_(from_address, to_address, value, method, receiver, escrow, token) - -### *class* human_protocol_sdk.transaction.transaction_utils.TransactionData(chain_id, block, tx_hash, from_address, to_address, timestamp, value, method, receiver, escrow, token, internal_transactions) - -Bases: `object` - -#### \_\_init_\_(chain_id, block, tx_hash, from_address, to_address, timestamp, value, method, receiver, escrow, token, internal_transactions) - -### *class* human_protocol_sdk.transaction.transaction_utils.TransactionUtils - -Bases: `object` - -A utility class that provides additional transaction-related functionalities. - -#### *static* get_transaction(chain_id, hash, options=None) - -Returns the transaction for a given hash. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Network in which the transaction was executed - * **hash** (`str`) – Hash of the transaction - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `Optional`[[`TransactionData`](#human_protocol_sdk.transaction.transaction_utils.TransactionData)] -* **Returns:** - Transaction data -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.transaction import TransactionUtils - - print( - TransactionUtils.get_transaction( - ChainId.POLYGON_AMOY, - "0x1234567890123456789012345678901234567891" - ) - ) - ``` - -#### *static* get_transactions(filter, options=None) - -Get an array of transactions based on the specified filter parameters. - -* **Parameters:** - * **filter** ([`TransactionFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.TransactionFilter)) – Object containing all the necessary parameters to filter - (chain_id, from_address, to_address, start_date, end_date, start_block, end_block, method, escrow, token, first, skip, order_direction) - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`TransactionData`](#human_protocol_sdk.transaction.transaction_utils.TransactionData)] -* **Returns:** - List of transactions -* **Example:** - ```python - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.transaction import TransactionUtils, TransactionFilter - - print( - TransactionUtils.get_transactions( - TransactionFilter( - chain_id=ChainId.POLYGON_AMOY, - from_address="0x1234567890123456789012345678901234567890", - to_address="0x0987654321098765432109876543210987654321", - method="transfer", - escrow="0x0987654321098765432109876543210987654321", - start_date=datetime.datetime(2023, 5, 8), - end_date=datetime.datetime(2023, 6, 8), - ) - ) - ) - ``` - -### *exception* human_protocol_sdk.transaction.transaction_utils.TransactionUtilsError - -Bases: `Exception` - -Raises when some error happens when getting data from subgraph. diff --git a/docs/sdk/python/human_protocol_sdk.utils.md b/docs/sdk/python/human_protocol_sdk.utils.md deleted file mode 100644 index e2b2289ca3..0000000000 --- a/docs/sdk/python/human_protocol_sdk.utils.md +++ /dev/null @@ -1,150 +0,0 @@ -# human_protocol_sdk.utils module - -### *class* human_protocol_sdk.utils.SubgraphOptions(max_retries=None, base_delay=None, indexer_id=None) - -Bases: `object` - -Configuration for subgraph logic. - -#### \_\_init_\_(max_retries=None, base_delay=None, indexer_id=None) - -#### base_delay *: `Optional`[`int`]* *= None* - -#### indexer_id *: `Optional`[`str`]* *= None* - -#### max_retries *: `Optional`[`int`]* *= None* - -### human_protocol_sdk.utils.custom_gql_fetch(network, query, params=None, options=None) - -Fetch data from the subgraph with optional logic. - -* **Parameters:** - * **network** (`dict`) – Network configuration dictionary - * **query** (`str`) – GraphQL query string - * **params** (`Optional`[`dict`]) – Query parameters - * **options** (`Optional`[[`SubgraphOptions`](#human_protocol_sdk.utils.SubgraphOptions)]) – Optional subgraph configuration -* **Returns:** - JSON response from the subgraph -* **Raises:** - **Exception** – If the subgraph query fails - -### human_protocol_sdk.utils.get_contract_interface(contract_entrypoint) - -Retrieve the contract interface of a given contract. - -* **Parameters:** - **contract_entrypoint** – the entrypoint of the JSON. -* **Returns:** - The contract interface containing the contract abi. - -### human_protocol_sdk.utils.get_erc20_interface() - -Retrieve the ERC20 interface. - -* **Returns:** - The ERC20 interface of smart contract. - -### human_protocol_sdk.utils.get_escrow_interface() - -Retrieve the RewardPool interface. - -* **Returns:** - The RewardPool interface of smart contract. - -### human_protocol_sdk.utils.get_factory_interface() - -Retrieve the EscrowFactory interface. - -* **Returns:** - The EscrowFactory interface of smart contract. - -### human_protocol_sdk.utils.get_hmt_balance(wallet_addr, token_addr, w3) - -Get HMT balance - -* **Parameters:** - * **wallet_addr** – wallet address - * **token_addr** – ERC-20 contract - * **w3** – Web3 instance -* **Returns:** - HMT balance (wei) - -### human_protocol_sdk.utils.get_kvstore_interface() - -Retrieve the KVStore interface. - -* **Returns:** - The KVStore interface of smart contract. - -### human_protocol_sdk.utils.get_staking_interface() - -Retrieve the Staking interface. - -* **Returns:** - The Staking interface of smart contract. - -### human_protocol_sdk.utils.handle_error(e, exception_class) - -Handles and translates errors raised during contract transactions. - -This function captures exceptions (especially ContractLogicError from web3.py), -extracts meaningful revert reasons if present, logs unexpected errors, and raises -a custom exception with a clear message for SDK users. - -* **Parameters:** - * **e** – The exception object raised during a transaction. - * **exception_class** – The custom exception class to raise (e.g., EscrowClientError). -* **Raises:** - **exception_class** – With a detailed error message, including contract revert reasons if available. -* **Example:** - try: - : tx_hash = contract.functions.someMethod(…).transact() - w3.eth.wait_for_transaction_receipt(tx_hash) - - except Exception as e: - : handle_error(e, EscrowClientError) - -### human_protocol_sdk.utils.is_indexer_error(error) - -Check if an error indicates that the indexer is down or not synced. -This function specifically checks for “bad indexers” errors from The Graph. - -* **Parameters:** - **error** (`Exception`) – The error to check -* **Return type:** - `bool` -* **Returns:** - True if the error indicates indexer issues - -### human_protocol_sdk.utils.parse_transfer_transaction(hmtoken_contract, tx_receipt) - -Parse a transfer transaction receipt. - -* **Parameters:** - * **hmtoken_contract** (`Contract`) – The HMT token contract - * **tx_receipt** (`Optional`[`TxReceipt`]) – The transaction receipt -* **Return type:** - `Tuple`[`bool`, `Optional`[`int`]] -* **Returns:** - A tuple indicating if HMT was transferred and the transaction balance - -### human_protocol_sdk.utils.validate_json(data) - -Validates if the given string is a valid JSON. -:type data: `str` -:param data: String to validate -:rtype: `bool` -:return: True if the string is a valid JSON, False otherwise - -### human_protocol_sdk.utils.validate_url(url) - -Validates the given URL. - -* **Parameters:** - **url** (`str`) – Public or private URL address -* **Return type:** - `bool` -* **Returns:** - True if URL is valid, False otherwise -* **Raises:** - **ValidationFailure** – If the URL is invalid diff --git a/docs/sdk/python/human_protocol_sdk.worker.md b/docs/sdk/python/human_protocol_sdk.worker.md deleted file mode 100644 index e62f9a998c..0000000000 --- a/docs/sdk/python/human_protocol_sdk.worker.md +++ /dev/null @@ -1,13 +0,0 @@ -# human_protocol_sdk.worker package - -This module enables to obtain worker information from subgraph. - -## Submodules - -* [human_protocol_sdk.worker.worker_utils module](human_protocol_sdk.worker.worker_utils.md) - * [`WorkerData`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerData) - * [`WorkerData.__init__()`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerData.__init__) - * [`WorkerUtils`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerUtils) - * [`WorkerUtils.get_worker()`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerUtils.get_worker) - * [`WorkerUtils.get_workers()`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerUtils.get_workers) - * [`WorkerUtilsError`](human_protocol_sdk.worker.worker_utils.md#human_protocol_sdk.worker.worker_utils.WorkerUtilsError) diff --git a/docs/sdk/python/human_protocol_sdk.worker.worker_utils.md b/docs/sdk/python/human_protocol_sdk.worker.worker_utils.md deleted file mode 100644 index 7c574445ad..0000000000 --- a/docs/sdk/python/human_protocol_sdk.worker.worker_utils.md +++ /dev/null @@ -1,52 +0,0 @@ -# human_protocol_sdk.worker.worker_utils module - -### *class* human_protocol_sdk.worker.worker_utils.WorkerData(id, address, total_amount_received, payout_count) - -Bases: `object` - -#### \_\_init_\_(id, address, total_amount_received, payout_count) - -Initializes a WorkerData instance. - -* **Parameters:** - * **id** (`str`) – Worker ID - * **address** (`str`) – Worker address - * **total_amount_received** (`str`) – Total amount received by the worker - * **payout_count** (`str`) – Number of payouts received by the worker - -### *class* human_protocol_sdk.worker.worker_utils.WorkerUtils - -Bases: `object` - -A utility class that provides additional worker-related functionalities. - -#### *static* get_worker(chain_id, worker_address, options=None) - -Gets the worker details. - -* **Parameters:** - * **chain_id** ([`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId)) – Network in which the worker exists - * **worker_address** (`str`) – Address of the worker - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `Optional`[[`WorkerData`](#human_protocol_sdk.worker.worker_utils.WorkerData)] -* **Returns:** - Worker data if exists, otherwise None - -#### *static* get_workers(filter, options=None) - -Get workers data of the protocol. - -* **Parameters:** - * **filter** ([`WorkerFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.WorkerFilter)) – Worker filter - * **options** (`Optional`[[`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions)]) – Optional config for subgraph requests -* **Return type:** - `List`[[`WorkerData`](#human_protocol_sdk.worker.worker_utils.WorkerData)] -* **Returns:** - List of workers data - -### *exception* human_protocol_sdk.worker.worker_utils.WorkerUtilsError - -Bases: `Exception` - -Raised when an error occurs when getting data from subgraph. diff --git a/docs/sdk/python/index.md b/docs/sdk/python/index.md deleted file mode 100644 index a8dc40c404..0000000000 --- a/docs/sdk/python/index.md +++ /dev/null @@ -1,83 +0,0 @@ - - -# Welcome to Human Protocol SDK’s documentation! - -## Installation - -To install the Human Protocol SDK, run the following command: - -```bash -pip install human-protocol-sdk -``` - -In case you want to use the features of the agreement module, make sure to install corresponding extras as well. - -```bash -pip install human-protocol-sdk[agreement] -``` - -## Contents: - -* [human_protocol_sdk package](human_protocol_sdk.md) - * [Subpackages](human_protocol_sdk.md#subpackages) - * [human_protocol_sdk.agreement package](human_protocol_sdk.agreement.md) - * [Getting Started](human_protocol_sdk.agreement.md#getting-started) - * [Submodules](human_protocol_sdk.agreement.md#submodules) - * [human_protocol_sdk.encryption package](human_protocol_sdk.encryption.md) - * [Submodules](human_protocol_sdk.encryption.md#submodules) - * [human_protocol_sdk.escrow package](human_protocol_sdk.escrow.md) - * [Submodules](human_protocol_sdk.escrow.md#submodules) - * [human_protocol_sdk.kvstore package](human_protocol_sdk.kvstore.md) - * [Submodules](human_protocol_sdk.kvstore.md#submodules) - * [human_protocol_sdk.operator package](human_protocol_sdk.operator.md) - * [Submodules](human_protocol_sdk.operator.md#submodules) - * [human_protocol_sdk.staking package](human_protocol_sdk.staking.md) - * [Submodules](human_protocol_sdk.staking.md#submodules) - * [human_protocol_sdk.statistics package](human_protocol_sdk.statistics.md) - * [Submodules](human_protocol_sdk.statistics.md#submodules) - * [human_protocol_sdk.storage package](human_protocol_sdk.storage.md) - * [Submodules](human_protocol_sdk.storage.md#submodules) - * [human_protocol_sdk.transaction package](human_protocol_sdk.transaction.md) - * [Submodules](human_protocol_sdk.transaction.md#submodules) - * [human_protocol_sdk.worker package](human_protocol_sdk.worker.md) - * [Submodules](human_protocol_sdk.worker.md#submodules) - * [Submodules](human_protocol_sdk.md#submodules) - * [human_protocol_sdk.constants module](human_protocol_sdk.constants.md) - * [`ChainId`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.ChainId) - * [`KVStoreKeys`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.KVStoreKeys) - * [`OperatorCategory`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OperatorCategory) - * [`OrderDirection`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.OrderDirection) - * [`Role`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Role) - * [`Status`](human_protocol_sdk.constants.md#human_protocol_sdk.constants.Status) - * [human_protocol_sdk.filter module](human_protocol_sdk.filter.md) - * [`CancellationRefundFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.CancellationRefundFilter) - * [`EscrowFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.EscrowFilter) - * [`FilterError`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.FilterError) - * [`PayoutFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.PayoutFilter) - * [`StakersFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StakersFilter) - * [`StatisticsFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatisticsFilter) - * [`StatusEventFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.StatusEventFilter) - * [`TransactionFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.TransactionFilter) - * [`WorkerFilter`](human_protocol_sdk.filter.md#human_protocol_sdk.filter.WorkerFilter) - * [human_protocol_sdk.legacy_encryption module](human_protocol_sdk.legacy_encryption.md) - * [`DecryptionError`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.DecryptionError) - * [`Encryption`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.Encryption) - * [`InvalidPublicKey`](human_protocol_sdk.legacy_encryption.md#human_protocol_sdk.legacy_encryption.InvalidPublicKey) - * [human_protocol_sdk.utils module](human_protocol_sdk.utils.md) - * [`SubgraphOptions`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.SubgraphOptions) - * [`custom_gql_fetch()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.custom_gql_fetch) - * [`get_contract_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_contract_interface) - * [`get_erc20_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_erc20_interface) - * [`get_escrow_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_escrow_interface) - * [`get_factory_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_factory_interface) - * [`get_hmt_balance()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_hmt_balance) - * [`get_kvstore_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_kvstore_interface) - * [`get_staking_interface()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.get_staking_interface) - * [`handle_error()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.handle_error) - * [`is_indexer_error()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.is_indexer_error) - * [`parse_transfer_transaction()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.parse_transfer_transaction) - * [`validate_json()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.validate_json) - * [`validate_url()`](human_protocol_sdk.utils.md#human_protocol_sdk.utils.validate_url) diff --git a/docs/sdk/typescript/README.md b/docs/sdk/typescript/README.md deleted file mode 100644 index 7644187242..0000000000 --- a/docs/sdk/typescript/README.md +++ /dev/null @@ -1,37 +0,0 @@ -**@human-protocol/sdk** - -*** - -

- Human Protocol -

- -[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 -[circleci-url]: https://circleci.com/gh/nestjs/nest - -

Human Protocol Node.js SDK

-

Node.js SDK to launch/manage escrows on Human Protocol -

- -

- - Node SDK Check - - - Node SDK deployment - -

- -## Installation - -This SDK is available on [NPM](https://www.npmjs.com/package/@human-protocol/sdk). - - yarn add @human-protocol/sdk - -## Documentation - -For detailed information about core, please refer to the [Human Protocol Docs](https://sdk.humanprotocol.org/). - -## License - -This project is licensed under the MIT License. See the [LICENSE](https://github.com/humanprotocol/human-protocol/blob/main/LICENSE) file for details. diff --git a/docs/sdk/typescript/base/README.md b/docs/sdk/typescript/base/README.md deleted file mode 100644 index 75875daaf1..0000000000 --- a/docs/sdk/typescript/base/README.md +++ /dev/null @@ -1,11 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / base - -# base - -## Classes - -- [BaseEthersClient](classes/BaseEthersClient.md) diff --git a/docs/sdk/typescript/base/classes/BaseEthersClient.md b/docs/sdk/typescript/base/classes/BaseEthersClient.md deleted file mode 100644 index 67d2394395..0000000000 --- a/docs/sdk/typescript/base/classes/BaseEthersClient.md +++ /dev/null @@ -1,63 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [base](../README.md) / BaseEthersClient - -# Abstract Class: BaseEthersClient - -Defined in: [base.ts:10](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L10) - -## Introduction - -This class is used as a base class for other clients making on-chain calls. - -## Extended by - -- [`EscrowClient`](../../escrow/classes/EscrowClient.md) -- [`KVStoreClient`](../../kvstore/classes/KVStoreClient.md) -- [`StakingClient`](../../staking/classes/StakingClient.md) - -## Constructors - -### Constructor - -> **new BaseEthersClient**(`runner`, `networkData`): `BaseEthersClient` - -Defined in: [base.ts:20](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L20) - -**BaseClient constructor** - -#### Parameters - -##### runner - -`ContractRunner` - -The Signer or Provider object to interact with the Ethereum network - -##### networkData - -[`NetworkData`](../../types/type-aliases/NetworkData.md) - -The network information required to connect to the contracts - -#### Returns - -`BaseEthersClient` - -## Properties - -### networkData - -> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) - -Defined in: [base.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) - -*** - -### runner - -> `protected` **runner**: `ContractRunner` - -Defined in: [base.ts:11](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) diff --git a/docs/sdk/typescript/encryption/README.md b/docs/sdk/typescript/encryption/README.md deleted file mode 100644 index ca6e9bf8d7..0000000000 --- a/docs/sdk/typescript/encryption/README.md +++ /dev/null @@ -1,12 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / encryption - -# encryption - -## Classes - -- [Encryption](classes/Encryption.md) -- [EncryptionUtils](classes/EncryptionUtils.md) diff --git a/docs/sdk/typescript/encryption/classes/Encryption.md b/docs/sdk/typescript/encryption/classes/Encryption.md deleted file mode 100644 index 1e622c6cfb..0000000000 --- a/docs/sdk/typescript/encryption/classes/Encryption.md +++ /dev/null @@ -1,257 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [encryption](../README.md) / Encryption - -# Class: Encryption - -Defined in: [encryption.ts:58](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L58) - -## Introduction - -Class for signing and decrypting messages. - -The algorithm includes the implementation of the [PGP encryption algorithm](https://github.com/openpgpjs/openpgpjs) multi-public key encryption on typescript, and uses the vanilla [ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) implementation Schnorr signature for signatures and [curve25519](https://en.wikipedia.org/wiki/Curve25519) for encryption. [Learn more](https://wiki.polkadot.network/docs/learn-cryptography). - -To get an instance of this class, initialization is recommended using the static `build` method. - -```ts -static async build(privateKeyArmored: string, passphrase?: string): Promise -``` - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Input parameters - -- `privateKeyArmored` - The encrypted private key in armored format. -- `passphrase` - The passphrase for the private key. - -## Code example - -```ts -import { Encryption } from '@human-protocol/sdk'; - -const privateKey = 'Armored_priv_key'; -const passphrase = 'example_passphrase'; -const encryption = await Encryption.build(privateKey, passphrase); -``` - -## Constructors - -### Constructor - -> **new Encryption**(`privateKey`): `Encryption` - -Defined in: [encryption.ts:66](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L66) - -Constructor for the Encryption class. - -#### Parameters - -##### privateKey - -`PrivateKey` - -The private key. - -#### Returns - -`Encryption` - -## Methods - -### decrypt() - -> **decrypt**(`message`, `publicKey?`): `Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\> - -Defined in: [encryption.ts:194](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L194) - -This function decrypts messages using the private key. In addition, the public key can be added for signature verification. - -#### Parameters - -##### message - -`string` - -Message to decrypt. - -##### publicKey? - -`string` - -Public key used to verify signature if needed. This is optional. - -#### Returns - -`Promise`\<`Uint8Array`\<`ArrayBufferLike`\>\> - -Message decrypted. - -**Code example** - -```ts -import { Encryption } from '@human-protocol/sdk'; - -const privateKey = 'Armored_priv_key'; -const passphrase = 'example_passphrase'; -const encryption = await Encryption.build(privateKey, passphrase); - -const publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v -WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME -CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF -X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS -CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 -YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc -UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv ------END PGP PUBLIC KEY BLOCK-----`; - -const resultMessage = await encryption.decrypt('message'); -``` - -*** - -### sign() - -> **sign**(`message`): `Promise`\<`string`\> - -Defined in: [encryption.ts:251](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L251) - -This function signs a message using the private key used to initialize the client. - -#### Parameters - -##### message - -`string` - -Message to sign. - -#### Returns - -`Promise`\<`string`\> - -Message signed. - -**Code example** - -```ts -import { Encryption } from '@human-protocol/sdk'; - -const privateKey = 'Armored_priv_key'; -const passphrase = 'example_passphrase'; -const encryption = await Encryption.build(privateKey, passphrase); - -const resultMessage = await encryption.sign('message'); -``` - -*** - -### signAndEncrypt() - -> **signAndEncrypt**(`message`, `publicKeys`): `Promise`\<`string`\> - -Defined in: [encryption.ts:142](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L142) - -This function signs and encrypts a message using the private key used to initialize the client and the specified public keys. - -#### Parameters - -##### message - -`MessageDataType` - -Message to sign and encrypt. - -##### publicKeys - -`string`[] - -Array of public keys to use for encryption. - -#### Returns - -`Promise`\<`string`\> - -Message signed and encrypted. - -**Code example** - -```ts -import { Encryption } from '@human-protocol/sdk'; -import { EscrowClient } from '@human-protocol/sdk'; - -const privateKey = 'Armored_priv_key'; -const passphrase = 'example_passphrase'; -const encryption = await Encryption.build(privateKey, passphrase); -const publicKey1 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v -WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME -CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF -X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS -CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 -YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc -UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv ------END PGP PUBLIC KEY BLOCK-----`; - -const publicKey2 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -xjMEZKQEMxYJKwYBBAHaRw8BAQdAG6h+E+6T/RV2tIHer3FP/jKThAyGcoVx -FzhnP0hncPzNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME -CwkHCAkQPIq5xLhlTYkDFQgKBBYAAgECGQECGwMCHgEWIQTcxtMgul/AeUvH -bio8irnEuGVNiQAA/HsBANpfFkxNYixpsBk8LlaaCaPy5f1/cWNPgODM9uzo -ciSTAQDtAYynu4dSJO9GbMuDuc0FaUHRWJK3mS6JkvedYL4oBM44BGSkBDMS -CisGAQQBl1UBBQEBB0DWbEG7DMhkeSc8ZPzrH8XNSCqS3t9y/oQidFR+xN3Z -bAMBCAfCeAQYFggAKgUCZKQEMwkQPIq5xLhlTYkCGwwWIQTcxtMgul/AeUvH -bio8irnEuGVNiQAAqt8BAM/4Lw0RVOb0L5Ki9CyxO/6AKvRg4ra3Q3WR+duP -s/88AQCDErzvn+SOX4s3gvZcM3Vr4wh4Q2syHV8Okgx8STYPDg===DsVk ------END PGP PUBLIC KEY BLOCK-----`; - -const publicKeys = [publicKey1, publicKey2]; -const resultMessage = await encryption.signAndEncrypt('message', publicKeys); -``` - -*** - -### build() - -> `static` **build**(`privateKeyArmored`, `passphrase?`): `Promise`\<`Encryption`\> - -Defined in: [encryption.ts:77](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L77) - -Builds an Encryption instance by decrypting the private key from an encrypted private key and passphrase. - -#### Parameters - -##### privateKeyArmored - -`string` - -The encrypted private key in armored format. - -##### passphrase? - -`string` - -Optional: The passphrase for the private key. - -#### Returns - -`Promise`\<`Encryption`\> - -- The Encryption instance. diff --git a/docs/sdk/typescript/encryption/classes/EncryptionUtils.md b/docs/sdk/typescript/encryption/classes/EncryptionUtils.md deleted file mode 100644 index 75f3cbcc88..0000000000 --- a/docs/sdk/typescript/encryption/classes/EncryptionUtils.md +++ /dev/null @@ -1,283 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [encryption](../README.md) / EncryptionUtils - -# Class: EncryptionUtils - -Defined in: [encryption.ts:290](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L290) - -## Introduction - -Utility class for encryption-related operations. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -```ts -import { EncryptionUtils } from '@human-protocol/sdk'; - -const keyPair = await EncryptionUtils.generateKeyPair('Human', 'human@hmt.ai'); -``` - -## Constructors - -### Constructor - -> **new EncryptionUtils**(): `EncryptionUtils` - -#### Returns - -`EncryptionUtils` - -## Methods - -### encrypt() - -> `static` **encrypt**(`message`, `publicKeys`): `Promise`\<`string`\> - -Defined in: [encryption.ts:444](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L444) - -This function encrypts a message using the specified public keys. - -#### Parameters - -##### message - -`MessageDataType` - -Message to encrypt. - -##### publicKeys - -`string`[] - -Array of public keys to use for encryption. - -#### Returns - -`Promise`\<`string`\> - -Message encrypted. - -**Code example** - -```ts -import { EncryptionUtils } from '@human-protocol/sdk'; - -const publicKey1 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v -WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME -CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF -X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS -CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 -YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc -UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv ------END PGP PUBLIC KEY BLOCK-----`; - -const publicKey2 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -xjMEZKQEMxYJKwYBBAHaRw8BAQdAG6h+E+6T/RV2tIHer3FP/jKThAyGcoVx -FzhnP0hncPzNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME -CwkHCAkQPIq5xLhlTYkDFQgKBBYAAgECGQECGwMCHgEWIQTcxtMgul/AeUvH -bio8irnEuGVNiQAA/HsBANpfFkxNYixpsBk8LlaaCaPy5f1/cWNPgODM9uzo -ciSTAQDtAYynu4dSJO9GbMuDuc0FaUHRWJK3mS6JkvedYL4oBM44BGSkBDMS -CisGAQQBl1UBBQEBB0DWbEG7DMhkeSc8ZPzrH8XNSCqS3t9y/oQidFR+xN3Z -bAMBCAfCeAQYFggAKgUCZKQEMwkQPIq5xLhlTYkCGwwWIQTcxtMgul/AeUvH -bio8irnEuGVNiQAAqt8BAM/4Lw0RVOb0L5Ki9CyxO/6AKvRg4ra3Q3WR+duP -s/88AQCDErzvn+SOX4s3gvZcM3Vr4wh4Q2syHV8Okgx8STYPDg===DsVk ------END PGP PUBLIC KEY BLOCK-----`; - -const publicKeys = [publicKey1, publicKey2] -const result = await EncryptionUtils.encrypt('message', publicKeys); -``` - -*** - -### generateKeyPair() - -> `static` **generateKeyPair**(`name`, `email`, `passphrase`): `Promise`\<[`IKeyPair`](../../interfaces/interfaces/IKeyPair.md)\> - -Defined in: [encryption.ts:382](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L382) - -This function generates a key pair for encryption and decryption. - -#### Parameters - -##### name - -`string` - -Name for the key pair. - -##### email - -`string` - -Email for the key pair. - -##### passphrase - -`string` = `''` - -Passphrase to encrypt the private key. Optional. - -#### Returns - -`Promise`\<[`IKeyPair`](../../interfaces/interfaces/IKeyPair.md)\> - -Key pair generated. - -**Code example** - -```ts -import { EncryptionUtils } from '@human-protocol/sdk'; - -const name = 'YOUR_NAME'; -const email = 'YOUR_EMAIL'; -const passphrase = 'YOUR_PASSPHRASE'; -const result = await EncryptionUtils.generateKeyPair(name, email, passphrase); -``` - -*** - -### getSignedData() - -> `static` **getSignedData**(`message`): `Promise`\<`string`\> - -Defined in: [encryption.ts:351](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L351) - -This function gets signed data from a signed message. - -#### Parameters - -##### message - -`string` - -Message. - -#### Returns - -`Promise`\<`string`\> - -Signed data. - -**Code example** - -```ts -import { EncryptionUtils } from '@human-protocol/sdk'; - -const signedData = await EncryptionUtils.getSignedData('message'); -``` - -*** - -### isEncrypted() - -> `static` **isEncrypted**(`message`): `boolean` - -Defined in: [encryption.ts:494](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L494) - -Verifies if a message appears to be encrypted with OpenPGP. - -#### Parameters - -##### message - -`string` - -Message to verify. - -#### Returns - -`boolean` - -`true` if the message appears to be encrypted, `false` if not. - -**Code example:** - -```ts -const message = `-----BEGIN PGP MESSAGE----- - -wV4DqdeRpqH+jaISAQdAsvBFxikvjxRqC7ZlDe98cLd7/aeCEI/AcL8PpVKK -mC0wKlwxNg/ADi55z9jcYFuMC4kKE+C/teM+JqiI8DO9AwassQUvKFtULnpx -h2jaOjC/0sAQASjUsIFK8zbuDgk/P8T9Npn6px+GlJPg9K90iwtPWiIp0eyW -4zXamJZT51k2DyaUX/Rsc6P4PYhQRKjt0yxtH0jHPmKkLC/9eBeFf4GP0zlZ -18xMZ8uCpQCma708Gz0sJYxEz3u/eZdHD7Mc7tWQKyJG8MsTwM1P+fdK1X75 -L9UryJG2AY+6kKZhG4dqjNxiO4fWluiB2u7iMF+iLEyE3SQCEYorWMC+NDWi -QIJZ7oQ2w7BaPo1a991gvTOSNm5v2x44KfqPI1uj859BjsQTCA== -=tsmI ------END PGP MESSAGE-----`; - -const isEncrypted = await EncryptionUtils.isEncrypted(message); - -if (isEncrypted) { - console.log('The message is encrypted with OpenPGP.'); -} else { - console.log('The message is not encrypted with OpenPGP.'); -} -``` - -*** - -### verify() - -> `static` **verify**(`message`, `publicKey`): `Promise`\<`boolean`\> - -Defined in: [encryption.ts:318](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts#L318) - -This function verifies the signature of a signed message using the public key. - -#### Parameters - -##### message - -`string` - -Message to verify. - -##### publicKey - -`string` - -Public key to verify that the message was signed by a specific source. - -#### Returns - -`Promise`\<`boolean`\> - -True if verified. False if not verified. - -**Code example** - -```ts -import { EncryptionUtils } from '@human-protocol/sdk'; - -const publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v -WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME -CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF -X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS -CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 -YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf -XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc -UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv ------END PGP PUBLIC KEY BLOCK-----`; - -const result = await EncryptionUtils.verify('message', publicKey); -``` diff --git a/docs/sdk/typescript/enums/README.md b/docs/sdk/typescript/enums/README.md deleted file mode 100644 index fde5e39c53..0000000000 --- a/docs/sdk/typescript/enums/README.md +++ /dev/null @@ -1,13 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / enums - -# enums - -## Enumerations - -- [ChainId](enumerations/ChainId.md) -- [OperatorCategory](enumerations/OperatorCategory.md) -- [OrderDirection](enumerations/OrderDirection.md) diff --git a/docs/sdk/typescript/enums/enumerations/ChainId.md b/docs/sdk/typescript/enums/enumerations/ChainId.md deleted file mode 100644 index 2a65625054..0000000000 --- a/docs/sdk/typescript/enums/enumerations/ChainId.md +++ /dev/null @@ -1,73 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [enums](../README.md) / ChainId - -# Enumeration: ChainId - -Defined in: [enums.ts:1](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L1) - -## Enumeration Members - -### ALL - -> **ALL**: `-1` - -Defined in: [enums.ts:2](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L2) - -*** - -### BSC\_MAINNET - -> **BSC\_MAINNET**: `56` - -Defined in: [enums.ts:5](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L5) - -*** - -### BSC\_TESTNET - -> **BSC\_TESTNET**: `97` - -Defined in: [enums.ts:6](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L6) - -*** - -### LOCALHOST - -> **LOCALHOST**: `1338` - -Defined in: [enums.ts:9](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L9) - -*** - -### MAINNET - -> **MAINNET**: `1` - -Defined in: [enums.ts:3](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L3) - -*** - -### POLYGON - -> **POLYGON**: `137` - -Defined in: [enums.ts:7](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L7) - -*** - -### POLYGON\_AMOY - -> **POLYGON\_AMOY**: `80002` - -Defined in: [enums.ts:8](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L8) - -*** - -### SEPOLIA - -> **SEPOLIA**: `11155111` - -Defined in: [enums.ts:4](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L4) diff --git a/docs/sdk/typescript/enums/enumerations/OperatorCategory.md b/docs/sdk/typescript/enums/enumerations/OperatorCategory.md deleted file mode 100644 index dcfb8ec5f7..0000000000 --- a/docs/sdk/typescript/enums/enumerations/OperatorCategory.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [enums](../README.md) / OperatorCategory - -# Enumeration: OperatorCategory - -Defined in: [enums.ts:17](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L17) - -## Enumeration Members - -### MACHINE\_LEARNING - -> **MACHINE\_LEARNING**: `"machine_learning"` - -Defined in: [enums.ts:18](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L18) - -*** - -### MARKET\_MAKING - -> **MARKET\_MAKING**: `"market_making"` - -Defined in: [enums.ts:19](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L19) diff --git a/docs/sdk/typescript/enums/enumerations/OrderDirection.md b/docs/sdk/typescript/enums/enumerations/OrderDirection.md deleted file mode 100644 index e02a68c904..0000000000 --- a/docs/sdk/typescript/enums/enumerations/OrderDirection.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [enums](../README.md) / OrderDirection - -# Enumeration: OrderDirection - -Defined in: [enums.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L12) - -## Enumeration Members - -### ASC - -> **ASC**: `"asc"` - -Defined in: [enums.ts:13](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L13) - -*** - -### DESC - -> **DESC**: `"desc"` - -Defined in: [enums.ts:14](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/enums.ts#L14) diff --git a/docs/sdk/typescript/escrow/README.md b/docs/sdk/typescript/escrow/README.md deleted file mode 100644 index 0d8dc6fd93..0000000000 --- a/docs/sdk/typescript/escrow/README.md +++ /dev/null @@ -1,12 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / escrow - -# escrow - -## Classes - -- [EscrowClient](classes/EscrowClient.md) -- [EscrowUtils](classes/EscrowUtils.md) diff --git a/docs/sdk/typescript/escrow/classes/EscrowClient.md b/docs/sdk/typescript/escrow/classes/EscrowClient.md deleted file mode 100644 index 6f353e103f..0000000000 --- a/docs/sdk/typescript/escrow/classes/EscrowClient.md +++ /dev/null @@ -1,1572 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [escrow](../README.md) / EscrowClient - -# Class: EscrowClient - -Defined in: [escrow.ts:148](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L148) - -## Introduction - -This client enables performing actions on Escrow contracts and obtaining information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the `runner`. -To use this client, it is recommended to initialize it using the static `build` method. - -```ts -static async build(runner: ContractRunner): Promise; -``` - -A `Signer` or a `Provider` should be passed depending on the use case of this module: - -- **Signer**: when the user wants to use this model to send transactions calling the contract functions. -- **Provider**: when the user wants to use this model to get information from the contracts or subgraph. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -### Signer - -**Using private key (backend)** - -```ts -import { EscrowClient } from '@human-protocol/sdk'; -import { Wallet, providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); -``` - -**Using Wagmi (frontend)** - -```ts -import { useSigner, useChainId } from 'wagmi'; -import { EscrowClient } from '@human-protocol/sdk'; - -const { data: signer } = useSigner(); -const escrowClient = await EscrowClient.build(signer); -``` - -### Provider - -```ts -import { EscrowClient } from '@human-protocol/sdk'; -import { providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); -``` - -## Extends - -- [`BaseEthersClient`](../../base/classes/BaseEthersClient.md) - -## Constructors - -### Constructor - -> **new EscrowClient**(`runner`, `networkData`): `EscrowClient` - -Defined in: [escrow.ts:157](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L157) - -**EscrowClient constructor** - -#### Parameters - -##### runner - -`ContractRunner` - -The Runner object to interact with the Ethereum network - -##### networkData - -[`NetworkData`](../../types/type-aliases/NetworkData.md) - -The network information required to connect to the Escrow contract - -#### Returns - -`EscrowClient` - -#### Overrides - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`constructor`](../../base/classes/BaseEthersClient.md#constructor) - -## Properties - -### networkData - -> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) - -Defined in: [base.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) - -#### Inherited from - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`networkData`](../../base/classes/BaseEthersClient.md#networkdata) - -*** - -### runner - -> `protected` **runner**: `ContractRunner` - -Defined in: [base.ts:11](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) - -#### Inherited from - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`runner`](../../base/classes/BaseEthersClient.md#runner) - -## Methods - -### bulkPayOut() - -#### Call Signature - -> **bulkPayOut**(`escrowAddress`, `recipients`, `amounts`, `finalResultsUrl`, `finalResultsHash`, `txId`, `forceComplete`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:803](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L803) - -This function pays out the amounts specified to the workers and sets the URL of the final results file. - -##### Parameters - -###### escrowAddress - -`string` - -Escrow address to payout. - -###### recipients - -`string`[] - -Array of recipient addresses. - -###### amounts - -`bigint`[] - -Array of amounts the recipients will receive. - -###### finalResultsUrl - -`string` - -Final results file URL. - -###### finalResultsHash - -`string` - -Final results file hash. - -###### txId - -`number` - -Transaction ID. - -###### forceComplete - -`boolean` - -Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). - -###### txOptions? - -`Overrides` - -Additional transaction parameters (optional, defaults to an empty object). - -##### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Reputation Oracle or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; -const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')]; -const resultsUrl = 'http://localhost/results.json'; -const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'; -const txId = 1; - -await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId, true); -``` - -#### Call Signature - -> **bulkPayOut**(`escrowAddress`, `recipients`, `amounts`, `finalResultsUrl`, `finalResultsHash`, `payoutId`, `forceComplete`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:853](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L853) - -This function pays out the amounts specified to the workers and sets the URL of the final results file. - -##### Parameters - -###### escrowAddress - -`string` - -Escrow address to payout. - -###### recipients - -`string`[] - -Array of recipient addresses. - -###### amounts - -`bigint`[] - -Array of amounts the recipients will receive. - -###### finalResultsUrl - -`string` - -Final results file URL. - -###### finalResultsHash - -`string` - -Final results file hash. - -###### payoutId - -`string` - -Payout ID. - -###### forceComplete - -`boolean` - -Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). - -###### txOptions? - -`Overrides` - -Additional transaction parameters (optional, defaults to an empty object). - -##### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Reputation Oracle or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; -import { v4 as uuidV4 } from 'uuid'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; -const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')]; -const resultsUrl = 'http://localhost/results.json'; -const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'; -const payoutId = uuidV4(); - -await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, payoutId, true); -``` - -*** - -### cancel() - -> **cancel**(`escrowAddress`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:952](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L952) - -This function cancels the specified escrow and sends the balance to the canceler. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow to cancel. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -**Code example** - -> Only Job Launcher or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.cancel('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -#### Returns - -`Promise`\<`void`\> - -*** - -### complete() - -> **complete**(`escrowAddress`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:743](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L743) - -This function sets the status of an escrow to completed. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Recording Oracle or admin can call it. - -```ts -import { Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.complete('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### createBulkPayoutTransaction() - -> **createBulkPayoutTransaction**(`escrowAddress`, `recipients`, `amounts`, `finalResultsUrl`, `finalResultsHash`, `payoutId`, `forceComplete`, `txOptions?`): `Promise`\<[`TransactionLikeWithNonce`](../../types/type-aliases/TransactionLikeWithNonce.md)\> - -Defined in: [escrow.ts:1150](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1150) - -Creates a prepared transaction for bulk payout without immediately sending it. - -#### Parameters - -##### escrowAddress - -`string` - -Escrow address to payout. - -##### recipients - -`string`[] - -Array of recipient addresses. - -##### amounts - -`bigint`[] - -Array of amounts the recipients will receive. - -##### finalResultsUrl - -`string` - -Final results file URL. - -##### finalResultsHash - -`string` - -Final results file hash. - -##### payoutId - -`string` - -Payout ID to identify the payout. - -##### forceComplete - -`boolean` = `false` - -Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<[`TransactionLikeWithNonce`](../../types/type-aliases/TransactionLikeWithNonce.md)\> - -Returns object with raw transaction and signed transaction hash - -**Code example** - -> Only Reputation Oracle or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY' - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; -const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')]; -const resultsUrl = 'http://localhost/results.json'; -const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'; -const payoutId = '372f6916-fe34-4711-b6e3-274f682047de'; - -const rawTransaction = await escrowClient.createBulkPayoutTransaction('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId); -console.log('Raw transaction:', rawTransaction); - -const signedTransaction = await signer.signTransaction(rawTransaction); -console.log('Tx hash:', ethers.keccak256(signedTransaction)); -(await signer.sendTransaction(rawTransaction)).wait(); - -*** - -### createEscrow() - -> **createEscrow**(`tokenAddress`, `jobRequesterId`, `txOptions?`): `Promise`\<`string`\> - -Defined in: [escrow.ts:235](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L235) - -This function creates an escrow contract that uses the token passed to pay oracle fees and reward workers. - -#### Parameters - -##### tokenAddress - -`string` - -The address of the token to use for escrow funding. - -##### jobRequesterId - -`string` - -Identifier for the job requester. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`string`\> - -Returns the address of the escrow created. - -**Code example** - -> Need to have available stake. - -```ts -import { Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const tokenAddress = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4'; -const jobRequesterId = "job-requester-id"; -const escrowAddress = await escrowClient.createEscrow(tokenAddress, jobRequesterId); -``` - -*** - -### createFundAndSetupEscrow() - -> **createFundAndSetupEscrow**(`tokenAddress`, `amount`, `jobRequesterId`, `escrowConfig`, `txOptions?`): `Promise`\<`string`\> - -Defined in: [escrow.ts:373](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L373) - -Creates, funds, and sets up a new escrow contract in a single transaction. - -#### Parameters - -##### tokenAddress - -`string` - -The ERC-20 token address used to fund the escrow. - -##### amount - -`bigint` - -The token amount to fund the escrow with. - -##### jobRequesterId - -`string` - -An off-chain identifier for the job requester. - -##### escrowConfig - -[`IEscrowConfig`](../../interfaces/interfaces/IEscrowConfig.md) - -Configuration parameters for escrow setup: - - `recordingOracle`: Address of the recording oracle. - - `reputationOracle`: Address of the reputation oracle. - - `exchangeOracle`: Address of the exchange oracle. - - `recordingOracleFee`: Fee (in basis points or percentage * 100) for the recording oracle. - - `reputationOracleFee`: Fee for the reputation oracle. - - `exchangeOracleFee`: Fee for the exchange oracle. - - `manifest`: URL to the manifest file. - - `manifestHash`: Hash of the manifest content. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`string`\> - -Returns the address of the escrow created. - -#### Example - -```ts -import { Wallet, ethers } from 'ethers'; -import { EscrowClient, IERC20__factory } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; -const provider = new ethers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); - -const escrowClient = await EscrowClient.build(signer); - -const tokenAddress = '0xTokenAddress'; -const amount = ethers.parseUnits('1000', 18); -const jobRequesterId = 'requester-123'; - -const token = IERC20__factory.connect(tokenAddress, signer); -await token.approve(escrowClient.escrowFactoryContract.target, amount); - -const escrowConfig = { - recordingOracle: '0xRecordingOracle', - reputationOracle: '0xReputationOracle', - exchangeOracle: '0xExchangeOracle', - recordingOracleFee: 5n, - reputationOracleFee: 5n, - exchangeOracleFee: 5n, - manifest: 'https://example.com/manifest.json', - manifestHash: 'manifestHash-123', -} satisfies IEscrowConfig; - -const escrowAddress = await escrowClient.createFundAndSetupEscrow( - tokenAddress, - amount, - jobRequesterId, - escrowConfig -); - -console.log('Escrow created at:', escrowAddress); -``` - -*** - -### fund() - -> **fund**(`escrowAddress`, `amount`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:546](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L546) - -This function adds funds of the chosen token to the escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow to fund. - -##### amount - -`bigint` - -Amount to be added as funds. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI -await escrowClient.fund('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); -``` - -*** - -### getBalance() - -> **getBalance**(`escrowAddress`): `Promise`\<`bigint`\> - -Defined in: [escrow.ts:1295](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1295) - -This function returns the balance for a specified escrow address. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`bigint`\> - -Balance of the escrow in the token used to fund it. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const balance = await escrowClient.getBalance('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getExchangeOracleAddress() - -> **getExchangeOracleAddress**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1756](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1756) - -This function returns the exchange oracle address for a given escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Address of the Exchange Oracle. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const oracleAddress = await escrowClient.getExchangeOracleAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getFactoryAddress() - -> **getFactoryAddress**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1794](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1794) - -This function returns the escrow factory address for a given escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Address of the escrow factory. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const factoryAddress = await escrowClient.getFactoryAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getIntermediateResultsHash() - -> **getIntermediateResultsHash**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1528](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1528) - -This function returns the intermediate results hash. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Hash of the intermediate results file content. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const intermediateResultsHash = await escrowClient.getIntermediateResultsHash('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getIntermediateResultsUrl() - -> **getIntermediateResultsUrl**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1490](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1490) - -This function returns the intermediate results file URL. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Url of the file that store results from Recording Oracle. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const intermediateResultsUrl = await escrowClient.getIntermediateResultsUrl('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getJobLauncherAddress() - -> **getJobLauncherAddress**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1680](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1680) - -This function returns the job launcher address for a given escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Address of the Job Launcher. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const jobLauncherAddress = await escrowClient.getJobLauncherAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getManifest() - -> **getManifest**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1414](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1414) - -This function returns the manifest. Could be a URL or a JSON string. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Url of the manifest. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const manifest = await escrowClient.getManifest('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getManifestHash() - -> **getManifestHash**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1376](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1376) - -This function returns the manifest file hash. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Hash of the manifest file content. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const manifestHash = await escrowClient.getManifestHash('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getRecordingOracleAddress() - -> **getRecordingOracleAddress**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1642](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1642) - -This function returns the recording oracle address for a given escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Address of the Recording Oracle. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const oracleAddress = await escrowClient.getRecordingOracleAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getReputationOracleAddress() - -> **getReputationOracleAddress**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1718](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1718) - -This function returns the reputation oracle address for a given escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Address of the Reputation Oracle. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const oracleAddress = await escrowClient.getReputationOracleAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getReservedFunds() - -> **getReservedFunds**(`escrowAddress`): `Promise`\<`bigint`\> - -Defined in: [escrow.ts:1339](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1339) - -This function returns the reserved funds for a specified escrow address. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`bigint`\> - -Reserved funds of the escrow in the token used to fund it. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const reservedFunds = await escrowClient.getReservedFunds('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getResultsUrl() - -> **getResultsUrl**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1452](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1452) - -This function returns the results file URL. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Results file url. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const resultsUrl = await escrowClient.getResultsUrl('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getStatus() - -> **getStatus**(`escrowAddress`): `Promise`\<[`EscrowStatus`](../../types/enumerations/EscrowStatus.md)\> - -Defined in: [escrow.ts:1604](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1604) - -This function returns the current status of the escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<[`EscrowStatus`](../../types/enumerations/EscrowStatus.md)\> - -Current status of the escrow. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const status = await escrowClient.getStatus('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getTokenAddress() - -> **getTokenAddress**(`escrowAddress`): `Promise`\<`string`\> - -Defined in: [escrow.ts:1566](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1566) - -This function returns the token address used for funding the escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow. - -#### Returns - -`Promise`\<`string`\> - -Address of the token used to fund the escrow. - -**Code example** - -```ts -import { providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const escrowClient = await EscrowClient.build(provider); - -const tokenAddress = await escrowClient.getTokenAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### requestCancellation() - -> **requestCancellation**(`escrowAddress`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:998](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L998) - -This function requests the cancellation of the specified escrow (moves status to ToCancel or finalizes if expired). - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow to request cancellation. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Job Launcher or admin can call it. - -```ts -import { Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.requestCancellation('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### setup() - -> **setup**(`escrowAddress`, `escrowConfig`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:470](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L470) - -This function sets up the parameters of the escrow. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow to set up. - -##### escrowConfig - -[`IEscrowConfig`](../../interfaces/interfaces/IEscrowConfig.md) - -Escrow configuration parameters. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Job Launcher or admin can call it. - -```ts -import { Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -const escrowAddress = '0x62dD51230A30401C455c8398d06F85e4EaB6309f'; -const escrowConfig = { - recordingOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - reputationOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - exchangeOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - recordingOracleFee: BigInt('10'), - reputationOracleFee: BigInt('10'), - exchangeOracleFee: BigInt('10'), - manifest: 'http://localhost/manifest.json', - manifestHash: 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', -}; -await escrowClient.setup(escrowAddress, escrowConfig); -``` - -*** - -### storeResults() - -#### Call Signature - -> **storeResults**(`escrowAddress`, `url`, `hash`, `fundsToReserve`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:612](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L612) - -This function stores the results URL and hash. - -##### Parameters - -###### escrowAddress - -`string` - -Address of the escrow. - -###### url - -`string` - -Results file URL. - -###### hash - -`string` - -Results file hash. - -###### fundsToReserve - -`bigint` - -Funds to reserve for payouts - -###### txOptions? - -`Overrides` - -Additional transaction parameters (optional, defaults to an empty object). - -##### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Recording Oracle or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'http://localhost/results.json', 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', ethers.parseEther('10')); -``` - -#### Call Signature - -> **storeResults**(`escrowAddress`, `url`, `hash`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [escrow.ts:648](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L648) - -This function stores the results URL and hash. - -##### Parameters - -###### escrowAddress - -`string` - -Address of the escrow. - -###### url - -`string` - -Results file URL. - -###### hash - -`string` - -Results file hash. - -###### txOptions? - -`Overrides` - -Additional transaction parameters (optional, defaults to an empty object). - -##### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Only Recording Oracle or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'http://localhost/results.json', 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'); -``` - -*** - -### withdraw() - -> **withdraw**(`escrowAddress`, `tokenAddress`, `txOptions?`): `Promise`\<[`IEscrowWithdraw`](../../interfaces/interfaces/IEscrowWithdraw.md)\> - -Defined in: [escrow.ts:1049](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1049) - -This function withdraws additional tokens in the escrow to the canceler. - -#### Parameters - -##### escrowAddress - -`string` - -Address of the escrow to withdraw. - -##### tokenAddress - -`string` - -Address of the token to withdraw. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<[`IEscrowWithdraw`](../../interfaces/interfaces/IEscrowWithdraw.md)\> - -Returns the escrow withdrawal data including transaction hash and withdrawal amount. Throws error if any. - -**Code example** - -> Only Job Launcher or admin can call it. - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { EscrowClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const escrowClient = await EscrowClient.build(signer); - -await escrowClient.withdraw( - '0x62dD51230A30401C455c8398d06F85e4EaB6309f', - '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4' -); -``` - -*** - -### build() - -> `static` **build**(`runner`): `Promise`\<`EscrowClient`\> - -Defined in: [escrow.ts:175](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L175) - -Creates an instance of EscrowClient from a Runner. - -#### Parameters - -##### runner - -`ContractRunner` - -The Runner object to interact with the Ethereum network - -#### Returns - -`Promise`\<`EscrowClient`\> - -An instance of EscrowClient - -#### Throws - -Thrown if the provider does not exist for the provided Signer - -#### Throws - -Thrown if the network's chainId is not supported diff --git a/docs/sdk/typescript/escrow/classes/EscrowUtils.md b/docs/sdk/typescript/escrow/classes/EscrowUtils.md deleted file mode 100644 index 68694e7429..0000000000 --- a/docs/sdk/typescript/escrow/classes/EscrowUtils.md +++ /dev/null @@ -1,538 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [escrow](../README.md) / EscrowUtils - -# Class: EscrowUtils - -Defined in: [escrow.ts:1843](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1843) - -## Introduction - -Utility class for escrow-related operations. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -### Signer - -**Using private key(backend)** - -```ts -import { ChainId, EscrowUtils } from '@human-protocol/sdk'; - -const escrowAddresses = new EscrowUtils.getEscrows({ - chainId: ChainId.POLYGON_AMOY -}); -``` - -## Constructors - -### Constructor - -> **new EscrowUtils**(): `EscrowUtils` - -#### Returns - -`EscrowUtils` - -## Methods - -### getCancellationRefund() - -> `static` **getCancellationRefund**(`chainId`, `escrowAddress`, `options?`): `Promise`\<[`ICancellationRefund`](../../interfaces/interfaces/ICancellationRefund.md) \| `null`\> - -Defined in: [escrow.ts:2435](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L2435) - -This function returns the cancellation refund for a given escrow address. - -> This uses Subgraph - -**Input parameters** - -```ts -enum ChainId { - ALL = -1, - MAINNET = 1, - SEPOLIA = 11155111, - BSC_MAINNET = 56, - BSC_TESTNET = 97, - POLYGON = 137, - POLYGON_AMOY = 80002, - LOCALHOST = 1338, -} -``` - -```ts -interface ICancellationRefund { - id: string; - escrowAddress: string; - receiver: string; - amount: bigint; - block: number; - timestamp: number; - txHash: string; -}; -``` - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the escrow has been deployed - -##### escrowAddress - -`string` - -Address of the escrow - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`ICancellationRefund`](../../interfaces/interfaces/ICancellationRefund.md) \| `null`\> - -Cancellation refund data - -**Code example** - -```ts -import { ChainId, EscrowUtils } from '@human-protocol/sdk'; - -const cancellationRefund = await EscrowUtils.getCancellationRefund(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890"); -``` - -*** - -### getCancellationRefunds() - -> `static` **getCancellationRefunds**(`filter`, `options?`): `Promise`\<[`ICancellationRefund`](../../interfaces/interfaces/ICancellationRefund.md)[]\> - -Defined in: [escrow.ts:2339](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L2339) - -This function returns the cancellation refunds for a given set of networks. - -> This uses Subgraph - -**Input parameters** - -```ts -enum ChainId { - ALL = -1, - MAINNET = 1, - SEPOLIA = 11155111, - BSC_MAINNET = 56, - BSC_TESTNET = 97, - POLYGON = 137, - POLYGON_AMOY = 80002, - LOCALHOST = 1338, -} -``` - -```ts -interface ICancellationRefund { - id: string; - escrowAddress: string; - receiver: string; - amount: bigint; - block: number; - timestamp: number; - txHash: string; -}; -``` - -#### Parameters - -##### filter - -[`ICancellationRefundFilter`](../../interfaces/interfaces/ICancellationRefundFilter.md) - -Filter parameters. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`ICancellationRefund`](../../interfaces/interfaces/ICancellationRefund.md)[]\> - -List of cancellation refunds matching the filters. - -**Code example** - -```ts -import { ChainId, EscrowUtils } from '@human-protocol/sdk'; - -const cancellationRefunds = await EscrowUtils.getCancellationRefunds({ - chainId: ChainId.POLYGON_AMOY, - escrowAddress: '0x1234567890123456789012345678901234567890', -}); -console.log(cancellationRefunds); -``` - -*** - -### getEscrow() - -> `static` **getEscrow**(`chainId`, `escrowAddress`, `options?`): `Promise`\<[`IEscrow`](../../interfaces/interfaces/IEscrow.md) \| `null`\> - -Defined in: [escrow.ts:2068](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L2068) - -This function returns the escrow data for a given address. - -> This uses Subgraph - -**Input parameters** - -```ts -enum ChainId { - ALL = -1, - MAINNET = 1, - SEPOLIA = 11155111, - BSC_MAINNET = 56, - BSC_TESTNET = 97, - POLYGON = 137, - POLYGON_AMOY = 80002, - LOCALHOST = 1338, -} -``` - -```ts -interface IEscrow { - id: string; - address: string; - amountPaid: bigint; - balance: bigint; - count: bigint; - factoryAddress: string; - finalResultsUrl: string | null; - finalResultsHash: string | null; - intermediateResultsUrl: string | null; - intermediateResultsHash: string | null; - launcher: string; - jobRequesterId: string | null; - manifestHash: string | null; - manifest: string | null; - recordingOracle: string | null; - reputationOracle: string | null; - exchangeOracle: string | null; - recordingOracleFee: number | null; - reputationOracleFee: number | null; - exchangeOracleFee: number | null; - status: string; - token: string; - totalFundedAmount: bigint; - createdAt: number; - chainId: number; -}; -``` - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the escrow has been deployed - -##### escrowAddress - -`string` - -Address of the escrow - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IEscrow`](../../interfaces/interfaces/IEscrow.md) \| `null`\> - -- Escrow data or null if not found. - -**Code example** - -```ts -import { ChainId, EscrowUtils } from '@human-protocol/sdk'; - -const escrow = new EscrowUtils.getEscrow(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890"); -``` - -*** - -### getEscrows() - -> `static` **getEscrows**(`filter`, `options?`): `Promise`\<[`IEscrow`](../../interfaces/interfaces/IEscrow.md)[]\> - -Defined in: [escrow.ts:1947](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L1947) - -This function returns an array of escrows based on the specified filter parameters. - -**Input parameters** - -```ts -interface IEscrowsFilter { - chainId: ChainId; - launcher?: string; - reputationOracle?: string; - recordingOracle?: string; - exchangeOracle?: string; - jobRequesterId?: string; - status?: EscrowStatus; - from?: Date; - to?: Date; - first?: number; - skip?: number; - orderDirection?: OrderDirection; -} -``` - -```ts -enum ChainId { - ALL = -1, - MAINNET = 1, - SEPOLIA = 11155111, - BSC_MAINNET = 56, - BSC_TESTNET = 97, - POLYGON = 137, - POLYGON_AMOY=80002, - LOCALHOST = 1338, -} -``` - -```ts -enum OrderDirection { - ASC = 'asc', - DESC = 'desc', -} -``` - -```ts -enum EscrowStatus { - Launched, - Pending, - Partial, - Paid, - Complete, - Cancelled, -} -``` - -```ts -interface IEscrow { - id: string; - address: string; - amountPaid: bigint; - balance: bigint; - count: bigint; - factoryAddress: string; - finalResultsUrl: string | null; - finalResultsHash: string | null; - intermediateResultsUrl: string | null; - intermediateResultsHash: string | null; - launcher: string; - jobRequesterId: string | null; - manifestHash: string | null; - manifest: string | null; - recordingOracle: string | null; - reputationOracle: string | null; - exchangeOracle: string | null; - recordingOracleFee: number | null; - reputationOracleFee: number | null; - exchangeOracleFee: number | null; - status: string; - token: string; - totalFundedAmount: bigint; - createdAt: number; - chainId: number; -}; -``` - -#### Parameters - -##### filter - -[`IEscrowsFilter`](../../interfaces/interfaces/IEscrowsFilter.md) - -Filter parameters. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IEscrow`](../../interfaces/interfaces/IEscrow.md)[]\> - -List of escrows that match the filter. - -**Code example** - -```ts -import { ChainId, EscrowUtils, EscrowStatus } from '@human-protocol/sdk'; - -const filters: IEscrowsFilter = { - status: EscrowStatus.Pending, - from: new Date(2023, 4, 8), - to: new Date(2023, 5, 8), - chainId: ChainId.POLYGON_AMOY -}; -const escrows = await EscrowUtils.getEscrows(filters); -``` - -*** - -### getPayouts() - -> `static` **getPayouts**(`filter`, `options?`): `Promise`\<[`IPayout`](../../interfaces/interfaces/IPayout.md)[]\> - -Defined in: [escrow.ts:2243](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L2243) - -This function returns the payouts for a given set of networks. - -> This uses Subgraph - -**Input parameters** -Fetch payouts from the subgraph. - -#### Parameters - -##### filter - -[`IPayoutFilter`](../../interfaces/interfaces/IPayoutFilter.md) - -Filter parameters. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IPayout`](../../interfaces/interfaces/IPayout.md)[]\> - -List of payouts matching the filters. - -**Code example** - -```ts -import { ChainId, EscrowUtils } from '@human-protocol/sdk'; - -const payouts = await EscrowUtils.getPayouts({ - chainId: ChainId.POLYGON, - escrowAddress: '0x1234567890123456789012345678901234567890', - recipient: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - from: new Date('2023-01-01'), - to: new Date('2023-12-31') -}); -console.log(payouts); -``` - -*** - -### getStatusEvents() - -> `static` **getStatusEvents**(`filter`, `options?`): `Promise`\<[`IStatusEvent`](../../interfaces/interfaces/IStatusEvent.md)[]\> - -Defined in: [escrow.ts:2151](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts#L2151) - -This function returns the status events for a given set of networks within an optional date range. - -> This uses Subgraph - -**Input parameters** - -```ts -enum ChainId { - ALL = -1, - MAINNET = 1, - SEPOLIA = 11155111, - BSC_MAINNET = 56, - BSC_TESTNET = 97, - POLYGON = 137, - POLYGON_AMOY = 80002, - LOCALHOST = 1338, -} -``` - -```ts -enum OrderDirection { - ASC = 'asc', - DESC = 'desc', -} -``` - -```ts -type Status = { - escrowAddress: string; - timestamp: string; - status: string; -}; -``` - -#### Parameters - -##### filter - -[`IStatusEventFilter`](../../interfaces/interfaces/IStatusEventFilter.md) - -Filter parameters. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IStatusEvent`](../../interfaces/interfaces/IStatusEvent.md)[]\> - -- Array of status events with their corresponding statuses. - -**Code example** - -```ts -import { ChainId, EscrowUtils, EscrowStatus } from '@human-protocol/sdk'; - -(async () => { - const fromDate = new Date('2023-01-01'); - const toDate = new Date('2023-12-31'); - const statusEvents = await EscrowUtils.getStatusEvents({ - chainId: ChainId.POLYGON, - statuses: [EscrowStatus.Pending, EscrowStatus.Complete], - from: fromDate, - to: toDate - }); - console.log(statusEvents); -})(); -``` diff --git a/docs/sdk/typescript/graphql/types/README.md b/docs/sdk/typescript/graphql/types/README.md deleted file mode 100644 index 9e93a2e90f..0000000000 --- a/docs/sdk/typescript/graphql/types/README.md +++ /dev/null @@ -1,29 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / graphql/types - -# graphql/types - -## Interfaces - -- [IOperatorSubgraph](interfaces/IOperatorSubgraph.md) -- [IReputationNetworkSubgraph](interfaces/IReputationNetworkSubgraph.md) - -## Type Aliases - -- [CancellationRefundData](type-aliases/CancellationRefundData.md) -- [EscrowData](type-aliases/EscrowData.md) -- [EscrowStatisticsData](type-aliases/EscrowStatisticsData.md) -- [EventDayData](type-aliases/EventDayData.md) -- [HMTHolderData](type-aliases/HMTHolderData.md) -- [HMTStatisticsData](type-aliases/HMTStatisticsData.md) -- [InternalTransactionData](type-aliases/InternalTransactionData.md) -- [KVStoreData](type-aliases/KVStoreData.md) -- [PayoutData](type-aliases/PayoutData.md) -- [RewardAddedEventData](type-aliases/RewardAddedEventData.md) -- [StakerData](type-aliases/StakerData.md) -- [StatusEvent](type-aliases/StatusEvent.md) -- [TransactionData](type-aliases/TransactionData.md) -- [WorkerData](type-aliases/WorkerData.md) diff --git a/docs/sdk/typescript/graphql/types/interfaces/IOperatorSubgraph.md b/docs/sdk/typescript/graphql/types/interfaces/IOperatorSubgraph.md deleted file mode 100644 index d94e596899..0000000000 --- a/docs/sdk/typescript/graphql/types/interfaces/IOperatorSubgraph.md +++ /dev/null @@ -1,141 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / IOperatorSubgraph - -# Interface: IOperatorSubgraph - -Defined in: [graphql/types.ts:143](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L143) - -## Properties - -### address - -> **address**: `string` - -Defined in: [graphql/types.ts:145](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L145) - -*** - -### amountJobsProcessed - -> **amountJobsProcessed**: `string` - -Defined in: [graphql/types.ts:146](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L146) - -*** - -### category - -> **category**: `string` \| `null` - -Defined in: [graphql/types.ts:156](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L156) - -*** - -### fee - -> **fee**: `string` \| `null` - -Defined in: [graphql/types.ts:148](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L148) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:144](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L144) - -*** - -### jobTypes - -> **jobTypes**: `string` \| `string`[] \| `null` - -Defined in: [graphql/types.ts:157](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L157) - -*** - -### name - -> **name**: `string` \| `null` - -Defined in: [graphql/types.ts:155](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L155) - -*** - -### publicKey - -> **publicKey**: `string` \| `null` - -Defined in: [graphql/types.ts:149](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L149) - -*** - -### registrationInstructions - -> **registrationInstructions**: `string` \| `null` - -Defined in: [graphql/types.ts:154](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L154) - -*** - -### registrationNeeded - -> **registrationNeeded**: `boolean` \| `null` - -Defined in: [graphql/types.ts:153](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L153) - -*** - -### reputationNetworks - -> **reputationNetworks**: `object`[] - -Defined in: [graphql/types.ts:158](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L158) - -#### address - -> **address**: `string` - -*** - -### role - -> **role**: `string` \| `null` - -Defined in: [graphql/types.ts:147](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L147) - -*** - -### staker - -> **staker**: \{ `lastDepositTimestamp`: `string`; `lockedAmount`: `string`; `lockedUntilTimestamp`: `string`; `slashedAmount`: `string`; `stakedAmount`: `string`; `withdrawnAmount`: `string`; \} \| `null` - -Defined in: [graphql/types.ts:159](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L159) - -*** - -### url - -> **url**: `string` \| `null` - -Defined in: [graphql/types.ts:152](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L152) - -*** - -### webhookUrl - -> **webhookUrl**: `string` \| `null` - -Defined in: [graphql/types.ts:150](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L150) - -*** - -### website - -> **website**: `string` \| `null` - -Defined in: [graphql/types.ts:151](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L151) diff --git a/docs/sdk/typescript/graphql/types/interfaces/IReputationNetworkSubgraph.md b/docs/sdk/typescript/graphql/types/interfaces/IReputationNetworkSubgraph.md deleted file mode 100644 index abeb311aa3..0000000000 --- a/docs/sdk/typescript/graphql/types/interfaces/IReputationNetworkSubgraph.md +++ /dev/null @@ -1,45 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / IReputationNetworkSubgraph - -# Interface: IReputationNetworkSubgraph - -Defined in: [graphql/types.ts:169](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L169) - -## Extends - -- `Omit`\<[`IReputationNetwork`](../../../interfaces/interfaces/IReputationNetwork.md), `"operators"`\> - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:42](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L42) - -#### Inherited from - -[`IReputationNetwork`](../../../interfaces/interfaces/IReputationNetwork.md).[`address`](../../../interfaces/interfaces/IReputationNetwork.md#address) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:41](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L41) - -#### Inherited from - -[`IReputationNetwork`](../../../interfaces/interfaces/IReputationNetwork.md).[`id`](../../../interfaces/interfaces/IReputationNetwork.md#id) - -*** - -### operators - -> **operators**: [`IOperatorSubgraph`](IOperatorSubgraph.md)[] - -Defined in: [graphql/types.ts:171](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L171) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/CancellationRefundData.md b/docs/sdk/typescript/graphql/types/type-aliases/CancellationRefundData.md deleted file mode 100644 index e0b294825e..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/CancellationRefundData.md +++ /dev/null @@ -1,67 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / CancellationRefundData - -# Type Alias: CancellationRefundData - -> **CancellationRefundData** = `object` - -Defined in: [graphql/types.ts:182](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L182) - -## Properties - -### amount - -> **amount**: `string` - -Defined in: [graphql/types.ts:186](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L186) - -*** - -### block - -> **block**: `string` - -Defined in: [graphql/types.ts:187](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L187) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [graphql/types.ts:184](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L184) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:183](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L183) - -*** - -### receiver - -> **receiver**: `string` - -Defined in: [graphql/types.ts:185](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L185) - -*** - -### timestamp - -> **timestamp**: `string` - -Defined in: [graphql/types.ts:188](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L188) - -*** - -### txHash - -> **txHash**: `string` - -Defined in: [graphql/types.ts:189](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L189) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md deleted file mode 100644 index adefaab72c..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/EscrowData.md +++ /dev/null @@ -1,203 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EscrowData - -# Type Alias: EscrowData - -> **EscrowData** = `object` - -Defined in: [graphql/types.ts:3](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L3) - -## Properties - -### address - -> **address**: `string` - -Defined in: [graphql/types.ts:5](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L5) - -*** - -### amountPaid - -> **amountPaid**: `string` - -Defined in: [graphql/types.ts:6](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L6) - -*** - -### balance - -> **balance**: `string` - -Defined in: [graphql/types.ts:7](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L7) - -*** - -### count - -> **count**: `string` - -Defined in: [graphql/types.ts:8](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L8) - -*** - -### createdAt - -> **createdAt**: `string` - -Defined in: [graphql/types.ts:27](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L27) - -*** - -### exchangeOracle - -> **exchangeOracle**: `string` \| `null` - -Defined in: [graphql/types.ts:20](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L20) - -*** - -### exchangeOracleFee - -> **exchangeOracleFee**: `string` \| `null` - -Defined in: [graphql/types.ts:23](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L23) - -*** - -### factoryAddress - -> **factoryAddress**: `string` - -Defined in: [graphql/types.ts:9](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L9) - -*** - -### finalResultsHash - -> **finalResultsHash**: `string` \| `null` - -Defined in: [graphql/types.ts:11](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L11) - -*** - -### finalResultsUrl - -> **finalResultsUrl**: `string` \| `null` - -Defined in: [graphql/types.ts:10](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L10) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:4](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L4) - -*** - -### intermediateResultsHash - -> **intermediateResultsHash**: `string` \| `null` - -Defined in: [graphql/types.ts:13](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L13) - -*** - -### intermediateResultsUrl - -> **intermediateResultsUrl**: `string` \| `null` - -Defined in: [graphql/types.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L12) - -*** - -### jobRequesterId - -> **jobRequesterId**: `string` \| `null` - -Defined in: [graphql/types.ts:15](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L15) - -*** - -### launcher - -> **launcher**: `string` - -Defined in: [graphql/types.ts:14](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L14) - -*** - -### manifest - -> **manifest**: `string` \| `null` - -Defined in: [graphql/types.ts:17](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L17) - -*** - -### manifestHash - -> **manifestHash**: `string` \| `null` - -Defined in: [graphql/types.ts:16](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L16) - -*** - -### recordingOracle - -> **recordingOracle**: `string` \| `null` - -Defined in: [graphql/types.ts:18](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L18) - -*** - -### recordingOracleFee - -> **recordingOracleFee**: `string` \| `null` - -Defined in: [graphql/types.ts:21](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L21) - -*** - -### reputationOracle - -> **reputationOracle**: `string` \| `null` - -Defined in: [graphql/types.ts:19](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L19) - -*** - -### reputationOracleFee - -> **reputationOracleFee**: `string` \| `null` - -Defined in: [graphql/types.ts:22](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L22) - -*** - -### status - -> **status**: `string` - -Defined in: [graphql/types.ts:24](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L24) - -*** - -### token - -> **token**: `string` - -Defined in: [graphql/types.ts:25](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L25) - -*** - -### totalFundedAmount - -> **totalFundedAmount**: `string` - -Defined in: [graphql/types.ts:26](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L26) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md b/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md deleted file mode 100644 index eb323e97c4..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/EscrowStatisticsData.md +++ /dev/null @@ -1,91 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EscrowStatisticsData - -# Type Alias: EscrowStatisticsData - -> **EscrowStatisticsData** = `object` - -Defined in: [graphql/types.ts:71](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L71) - -## Properties - -### bulkPayoutEventCount - -> **bulkPayoutEventCount**: `string` - -Defined in: [graphql/types.ts:74](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L74) - -*** - -### cancelledStatusEventCount - -> **cancelledStatusEventCount**: `string` - -Defined in: [graphql/types.ts:76](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L76) - -*** - -### completedStatusEventCount - -> **completedStatusEventCount**: `string` - -Defined in: [graphql/types.ts:79](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L79) - -*** - -### fundEventCount - -> **fundEventCount**: `string` - -Defined in: [graphql/types.ts:72](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L72) - -*** - -### paidStatusEventCount - -> **paidStatusEventCount**: `string` - -Defined in: [graphql/types.ts:78](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L78) - -*** - -### partialStatusEventCount - -> **partialStatusEventCount**: `string` - -Defined in: [graphql/types.ts:77](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L77) - -*** - -### pendingStatusEventCount - -> **pendingStatusEventCount**: `string` - -Defined in: [graphql/types.ts:75](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L75) - -*** - -### storeResultsEventCount - -> **storeResultsEventCount**: `string` - -Defined in: [graphql/types.ts:73](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L73) - -*** - -### totalEscrowCount - -> **totalEscrowCount**: `string` - -Defined in: [graphql/types.ts:81](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L81) - -*** - -### totalEventCount - -> **totalEventCount**: `string` - -Defined in: [graphql/types.ts:80](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L80) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md b/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md deleted file mode 100644 index 45f63bd761..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/EventDayData.md +++ /dev/null @@ -1,155 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / EventDayData - -# Type Alias: EventDayData - -> **EventDayData** = `object` - -Defined in: [graphql/types.ts:84](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L84) - -## Properties - -### dailyBulkPayoutEventCount - -> **dailyBulkPayoutEventCount**: `string` - -Defined in: [graphql/types.ts:88](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L88) - -*** - -### dailyCancelledStatusEventCount - -> **dailyCancelledStatusEventCount**: `string` - -Defined in: [graphql/types.ts:90](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L90) - -*** - -### dailyCompletedStatusEventCount - -> **dailyCompletedStatusEventCount**: `string` - -Defined in: [graphql/types.ts:93](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L93) - -*** - -### dailyEscrowCount - -> **dailyEscrowCount**: `string` - -Defined in: [graphql/types.ts:95](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L95) - -*** - -### dailyFundEventCount - -> **dailyFundEventCount**: `string` - -Defined in: [graphql/types.ts:86](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L86) - -*** - -### dailyHMTPayoutAmount - -> **dailyHMTPayoutAmount**: `string` - -Defined in: [graphql/types.ts:98](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L98) - -*** - -### dailyHMTTransferAmount - -> **dailyHMTTransferAmount**: `string` - -Defined in: [graphql/types.ts:100](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L100) - -*** - -### dailyHMTTransferCount - -> **dailyHMTTransferCount**: `string` - -Defined in: [graphql/types.ts:99](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L99) - -*** - -### dailyPaidStatusEventCount - -> **dailyPaidStatusEventCount**: `string` - -Defined in: [graphql/types.ts:92](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L92) - -*** - -### dailyPartialStatusEventCount - -> **dailyPartialStatusEventCount**: `string` - -Defined in: [graphql/types.ts:91](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L91) - -*** - -### dailyPayoutCount - -> **dailyPayoutCount**: `string` - -Defined in: [graphql/types.ts:97](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L97) - -*** - -### dailyPendingStatusEventCount - -> **dailyPendingStatusEventCount**: `string` - -Defined in: [graphql/types.ts:89](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L89) - -*** - -### dailyStoreResultsEventCount - -> **dailyStoreResultsEventCount**: `string` - -Defined in: [graphql/types.ts:87](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L87) - -*** - -### dailyTotalEventCount - -> **dailyTotalEventCount**: `string` - -Defined in: [graphql/types.ts:94](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L94) - -*** - -### dailyUniqueReceivers - -> **dailyUniqueReceivers**: `string` - -Defined in: [graphql/types.ts:102](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L102) - -*** - -### dailyUniqueSenders - -> **dailyUniqueSenders**: `string` - -Defined in: [graphql/types.ts:101](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L101) - -*** - -### dailyWorkerCount - -> **dailyWorkerCount**: `string` - -Defined in: [graphql/types.ts:96](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L96) - -*** - -### timestamp - -> **timestamp**: `string` - -Defined in: [graphql/types.ts:85](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L85) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md deleted file mode 100644 index 081a4eecf1..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/HMTHolderData.md +++ /dev/null @@ -1,27 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / HMTHolderData - -# Type Alias: HMTHolderData - -> **HMTHolderData** = `object` - -Defined in: [graphql/types.ts:112](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L112) - -## Properties - -### address - -> **address**: `string` - -Defined in: [graphql/types.ts:113](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L113) - -*** - -### balance - -> **balance**: `string` - -Defined in: [graphql/types.ts:114](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L114) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md b/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md deleted file mode 100644 index 2359e61314..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/HMTStatisticsData.md +++ /dev/null @@ -1,59 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / HMTStatisticsData - -# Type Alias: HMTStatisticsData - -> **HMTStatisticsData** = `object` - -Defined in: [graphql/types.ts:62](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L62) - -## Properties - -### holders - -> **holders**: `string` - -Defined in: [graphql/types.ts:68](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L68) - -*** - -### totalApprovalEventCount - -> **totalApprovalEventCount**: `string` - -Defined in: [graphql/types.ts:65](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L65) - -*** - -### totalBulkApprovalEventCount - -> **totalBulkApprovalEventCount**: `string` - -Defined in: [graphql/types.ts:66](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L66) - -*** - -### totalBulkTransferEventCount - -> **totalBulkTransferEventCount**: `string` - -Defined in: [graphql/types.ts:64](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L64) - -*** - -### totalTransferEventCount - -> **totalTransferEventCount**: `string` - -Defined in: [graphql/types.ts:63](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L63) - -*** - -### totalValueTransfered - -> **totalValueTransfered**: `string` - -Defined in: [graphql/types.ts:67](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L67) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/InternalTransactionData.md b/docs/sdk/typescript/graphql/types/type-aliases/InternalTransactionData.md deleted file mode 100644 index 1cd45eafa9..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/InternalTransactionData.md +++ /dev/null @@ -1,75 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / InternalTransactionData - -# Type Alias: InternalTransactionData - -> **InternalTransactionData** = `object` - -Defined in: [graphql/types.ts:37](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L37) - -## Properties - -### escrow - -> **escrow**: `string` \| `null` - -Defined in: [graphql/types.ts:43](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L43) - -*** - -### from - -> **from**: `string` - -Defined in: [graphql/types.ts:38](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L38) - -*** - -### id - -> **id**: `string` \| `null` - -Defined in: [graphql/types.ts:45](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L45) - -*** - -### method - -> **method**: `string` - -Defined in: [graphql/types.ts:41](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L41) - -*** - -### receiver - -> **receiver**: `string` \| `null` - -Defined in: [graphql/types.ts:42](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L42) - -*** - -### to - -> **to**: `string` - -Defined in: [graphql/types.ts:39](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L39) - -*** - -### token - -> **token**: `string` \| `null` - -Defined in: [graphql/types.ts:44](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L44) - -*** - -### value - -> **value**: `string` - -Defined in: [graphql/types.ts:40](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L40) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md b/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md deleted file mode 100644 index d7b229b9f0..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/KVStoreData.md +++ /dev/null @@ -1,59 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / KVStoreData - -# Type Alias: KVStoreData - -> **KVStoreData** = `object` - -Defined in: [graphql/types.ts:123](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L123) - -## Properties - -### address - -> **address**: `string` - -Defined in: [graphql/types.ts:125](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L125) - -*** - -### block - -> **block**: `string` - -Defined in: [graphql/types.ts:129](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L129) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:124](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L124) - -*** - -### key - -> **key**: `string` - -Defined in: [graphql/types.ts:126](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L126) - -*** - -### timestamp - -> **timestamp**: `Date` - -Defined in: [graphql/types.ts:128](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L128) - -*** - -### value - -> **value**: `string` - -Defined in: [graphql/types.ts:127](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L127) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md b/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md deleted file mode 100644 index 31d0634ce1..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/PayoutData.md +++ /dev/null @@ -1,51 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / PayoutData - -# Type Alias: PayoutData - -> **PayoutData** = `object` - -Defined in: [graphql/types.ts:174](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L174) - -## Properties - -### amount - -> **amount**: `string` - -Defined in: [graphql/types.ts:178](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L178) - -*** - -### createdAt - -> **createdAt**: `string` - -Defined in: [graphql/types.ts:179](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L179) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [graphql/types.ts:176](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L176) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:175](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L175) - -*** - -### recipient - -> **recipient**: `string` - -Defined in: [graphql/types.ts:177](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L177) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md b/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md deleted file mode 100644 index 0526b1f7dd..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/RewardAddedEventData.md +++ /dev/null @@ -1,43 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / RewardAddedEventData - -# Type Alias: RewardAddedEventData - -> **RewardAddedEventData** = `object` - -Defined in: [graphql/types.ts:105](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L105) - -## Properties - -### amount - -> **amount**: `string` - -Defined in: [graphql/types.ts:109](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L109) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [graphql/types.ts:106](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L106) - -*** - -### slasher - -> **slasher**: `string` - -Defined in: [graphql/types.ts:108](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L108) - -*** - -### staker - -> **staker**: `string` - -Defined in: [graphql/types.ts:107](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L107) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/StakerData.md b/docs/sdk/typescript/graphql/types/type-aliases/StakerData.md deleted file mode 100644 index 7947db29fb..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/StakerData.md +++ /dev/null @@ -1,75 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / StakerData - -# Type Alias: StakerData - -> **StakerData** = `object` - -Defined in: [graphql/types.ts:132](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L132) - -## Properties - -### address - -> **address**: `string` - -Defined in: [graphql/types.ts:134](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L134) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:133](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L133) - -*** - -### lastDepositTimestamp - -> **lastDepositTimestamp**: `string` - -Defined in: [graphql/types.ts:140](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L140) - -*** - -### lockedAmount - -> **lockedAmount**: `string` - -Defined in: [graphql/types.ts:136](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L136) - -*** - -### lockedUntilTimestamp - -> **lockedUntilTimestamp**: `string` - -Defined in: [graphql/types.ts:139](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L139) - -*** - -### slashedAmount - -> **slashedAmount**: `string` - -Defined in: [graphql/types.ts:138](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L138) - -*** - -### stakedAmount - -> **stakedAmount**: `string` - -Defined in: [graphql/types.ts:135](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L135) - -*** - -### withdrawnAmount - -> **withdrawnAmount**: `string` - -Defined in: [graphql/types.ts:137](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L137) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md b/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md deleted file mode 100644 index 97325a8485..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/StatusEvent.md +++ /dev/null @@ -1,35 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / StatusEvent - -# Type Alias: StatusEvent - -> **StatusEvent** = `object` - -Defined in: [graphql/types.ts:117](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L117) - -## Properties - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [graphql/types.ts:119](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L119) - -*** - -### status - -> **status**: `string` - -Defined in: [graphql/types.ts:120](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L120) - -*** - -### timestamp - -> **timestamp**: `string` - -Defined in: [graphql/types.ts:118](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L118) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/TransactionData.md b/docs/sdk/typescript/graphql/types/type-aliases/TransactionData.md deleted file mode 100644 index 97f53a8542..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/TransactionData.md +++ /dev/null @@ -1,99 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / TransactionData - -# Type Alias: TransactionData - -> **TransactionData** = `object` - -Defined in: [graphql/types.ts:48](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L48) - -## Properties - -### block - -> **block**: `string` - -Defined in: [graphql/types.ts:49](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L49) - -*** - -### escrow - -> **escrow**: `string` \| `null` - -Defined in: [graphql/types.ts:57](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L57) - -*** - -### from - -> **from**: `string` - -Defined in: [graphql/types.ts:51](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L51) - -*** - -### internalTransactions - -> **internalTransactions**: [`InternalTransactionData`](InternalTransactionData.md)[] - -Defined in: [graphql/types.ts:59](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L59) - -*** - -### method - -> **method**: `string` - -Defined in: [graphql/types.ts:55](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L55) - -*** - -### receiver - -> **receiver**: `string` \| `null` - -Defined in: [graphql/types.ts:56](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L56) - -*** - -### timestamp - -> **timestamp**: `string` - -Defined in: [graphql/types.ts:53](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L53) - -*** - -### to - -> **to**: `string` - -Defined in: [graphql/types.ts:52](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L52) - -*** - -### token - -> **token**: `string` \| `null` - -Defined in: [graphql/types.ts:58](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L58) - -*** - -### txHash - -> **txHash**: `string` - -Defined in: [graphql/types.ts:50](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L50) - -*** - -### value - -> **value**: `string` - -Defined in: [graphql/types.ts:54](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L54) diff --git a/docs/sdk/typescript/graphql/types/type-aliases/WorkerData.md b/docs/sdk/typescript/graphql/types/type-aliases/WorkerData.md deleted file mode 100644 index c7d57e521b..0000000000 --- a/docs/sdk/typescript/graphql/types/type-aliases/WorkerData.md +++ /dev/null @@ -1,43 +0,0 @@ -[**@human-protocol/sdk**](../../../README.md) - -*** - -[@human-protocol/sdk](../../../modules.md) / [graphql/types](../README.md) / WorkerData - -# Type Alias: WorkerData - -> **WorkerData** = `object` - -Defined in: [graphql/types.ts:30](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L30) - -## Properties - -### address - -> **address**: `string` - -Defined in: [graphql/types.ts:32](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L32) - -*** - -### id - -> **id**: `string` - -Defined in: [graphql/types.ts:31](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L31) - -*** - -### payoutCount - -> **payoutCount**: `string` - -Defined in: [graphql/types.ts:34](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L34) - -*** - -### totalHMTAmountReceived - -> **totalHMTAmountReceived**: `string` - -Defined in: [graphql/types.ts:33](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/graphql/types.ts#L33) diff --git a/docs/sdk/typescript/interfaces/README.md b/docs/sdk/typescript/interfaces/README.md deleted file mode 100644 index 8c3ffb229b..0000000000 --- a/docs/sdk/typescript/interfaces/README.md +++ /dev/null @@ -1,47 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / interfaces - -# interfaces - -## Interfaces - -- [ICancellationRefund](interfaces/ICancellationRefund.md) -- [ICancellationRefundFilter](interfaces/ICancellationRefundFilter.md) -- [IDailyEscrow](interfaces/IDailyEscrow.md) -- [IDailyHMT](interfaces/IDailyHMT.md) -- [IDailyPayment](interfaces/IDailyPayment.md) -- [IDailyWorker](interfaces/IDailyWorker.md) -- [IEscrow](interfaces/IEscrow.md) -- [IEscrowConfig](interfaces/IEscrowConfig.md) -- [IEscrowsFilter](interfaces/IEscrowsFilter.md) -- [IEscrowStatistics](interfaces/IEscrowStatistics.md) -- [IEscrowWithdraw](interfaces/IEscrowWithdraw.md) -- [IHMTHolder](interfaces/IHMTHolder.md) -- [IHMTHoldersParams](interfaces/IHMTHoldersParams.md) -- [IHMTStatistics](interfaces/IHMTStatistics.md) -- [IKeyPair](interfaces/IKeyPair.md) -- [IKVStore](interfaces/IKVStore.md) -- [InternalTransaction](interfaces/InternalTransaction.md) -- [IOperator](interfaces/IOperator.md) -- [IOperatorsFilter](interfaces/IOperatorsFilter.md) -- [IPagination](interfaces/IPagination.md) -- [IPaymentStatistics](interfaces/IPaymentStatistics.md) -- [IPayout](interfaces/IPayout.md) -- [IPayoutFilter](interfaces/IPayoutFilter.md) -- [IReputationNetwork](interfaces/IReputationNetwork.md) -- [IReward](interfaces/IReward.md) -- [IStaker](interfaces/IStaker.md) -- [IStakersFilter](interfaces/IStakersFilter.md) -- [IStatisticsFilter](interfaces/IStatisticsFilter.md) -- [IStatusEvent](interfaces/IStatusEvent.md) -- [IStatusEventFilter](interfaces/IStatusEventFilter.md) -- [ITransaction](interfaces/ITransaction.md) -- [ITransactionsFilter](interfaces/ITransactionsFilter.md) -- [IWorker](interfaces/IWorker.md) -- [IWorkersFilter](interfaces/IWorkersFilter.md) -- [IWorkerStatistics](interfaces/IWorkerStatistics.md) -- [StakerInfo](interfaces/StakerInfo.md) -- [SubgraphOptions](interfaces/SubgraphOptions.md) diff --git a/docs/sdk/typescript/interfaces/interfaces/ICancellationRefund.md b/docs/sdk/typescript/interfaces/interfaces/ICancellationRefund.md deleted file mode 100644 index 2092fbeb8e..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/ICancellationRefund.md +++ /dev/null @@ -1,65 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ICancellationRefund - -# Interface: ICancellationRefund - -Defined in: [interfaces.ts:292](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L292) - -## Properties - -### amount - -> **amount**: `bigint` - -Defined in: [interfaces.ts:296](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L296) - -*** - -### block - -> **block**: `number` - -Defined in: [interfaces.ts:297](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L297) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [interfaces.ts:294](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L294) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:293](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L293) - -*** - -### receiver - -> **receiver**: `string` - -Defined in: [interfaces.ts:295](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L295) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:298](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L298) - -*** - -### txHash - -> **txHash**: `string` - -Defined in: [interfaces.ts:299](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L299) diff --git a/docs/sdk/typescript/interfaces/interfaces/ICancellationRefundFilter.md b/docs/sdk/typescript/interfaces/interfaces/ICancellationRefundFilter.md deleted file mode 100644 index 656f138e73..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/ICancellationRefundFilter.md +++ /dev/null @@ -1,89 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ICancellationRefundFilter - -# Interface: ICancellationRefundFilter - -Defined in: [interfaces.ts:224](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L224) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:225](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L225) - -*** - -### escrowAddress? - -> `optional` **escrowAddress**: `string` - -Defined in: [interfaces.ts:226](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L226) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### from? - -> `optional` **from**: `Date` - -Defined in: [interfaces.ts:228](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L228) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### receiver? - -> `optional` **receiver**: `string` - -Defined in: [interfaces.ts:227](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L227) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) - -*** - -### to? - -> `optional` **to**: `Date` - -Defined in: [interfaces.ts:229](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L229) diff --git a/docs/sdk/typescript/interfaces/interfaces/IDailyEscrow.md b/docs/sdk/typescript/interfaces/interfaces/IDailyEscrow.md deleted file mode 100644 index 61395c4264..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IDailyEscrow.md +++ /dev/null @@ -1,57 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IDailyEscrow - -# Interface: IDailyEscrow - -Defined in: [interfaces.ts:232](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L232) - -## Properties - -### escrowsCancelled - -> **escrowsCancelled**: `number` - -Defined in: [interfaces.ts:238](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L238) - -*** - -### escrowsPaid - -> **escrowsPaid**: `number` - -Defined in: [interfaces.ts:237](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L237) - -*** - -### escrowsPending - -> **escrowsPending**: `number` - -Defined in: [interfaces.ts:235](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L235) - -*** - -### escrowsSolved - -> **escrowsSolved**: `number` - -Defined in: [interfaces.ts:236](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L236) - -*** - -### escrowsTotal - -> **escrowsTotal**: `number` - -Defined in: [interfaces.ts:234](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L234) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:233](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L233) diff --git a/docs/sdk/typescript/interfaces/interfaces/IDailyHMT.md b/docs/sdk/typescript/interfaces/interfaces/IDailyHMT.md deleted file mode 100644 index fd697e470f..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IDailyHMT.md +++ /dev/null @@ -1,49 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IDailyHMT - -# Interface: IDailyHMT - -Defined in: [interfaces.ts:277](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L277) - -## Properties - -### dailyUniqueReceivers - -> **dailyUniqueReceivers**: `number` - -Defined in: [interfaces.ts:282](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L282) - -*** - -### dailyUniqueSenders - -> **dailyUniqueSenders**: `number` - -Defined in: [interfaces.ts:281](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L281) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:278](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L278) - -*** - -### totalTransactionAmount - -> **totalTransactionAmount**: `bigint` - -Defined in: [interfaces.ts:279](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L279) - -*** - -### totalTransactionCount - -> **totalTransactionCount**: `number` - -Defined in: [interfaces.ts:280](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L280) diff --git a/docs/sdk/typescript/interfaces/interfaces/IDailyPayment.md b/docs/sdk/typescript/interfaces/interfaces/IDailyPayment.md deleted file mode 100644 index 2e12e938e8..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IDailyPayment.md +++ /dev/null @@ -1,41 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IDailyPayment - -# Interface: IDailyPayment - -Defined in: [interfaces.ts:255](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L255) - -## Properties - -### averageAmountPerWorker - -> **averageAmountPerWorker**: `bigint` - -Defined in: [interfaces.ts:259](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L259) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:256](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L256) - -*** - -### totalAmountPaid - -> **totalAmountPaid**: `bigint` - -Defined in: [interfaces.ts:257](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L257) - -*** - -### totalCount - -> **totalCount**: `number` - -Defined in: [interfaces.ts:258](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L258) diff --git a/docs/sdk/typescript/interfaces/interfaces/IDailyWorker.md b/docs/sdk/typescript/interfaces/interfaces/IDailyWorker.md deleted file mode 100644 index 935861839f..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IDailyWorker.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IDailyWorker - -# Interface: IDailyWorker - -Defined in: [interfaces.ts:246](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L246) - -## Properties - -### activeWorkers - -> **activeWorkers**: `number` - -Defined in: [interfaces.ts:248](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L248) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:247](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L247) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrow.md b/docs/sdk/typescript/interfaces/interfaces/IEscrow.md deleted file mode 100644 index 669953a6b8..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrow.md +++ /dev/null @@ -1,209 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrow - -# Interface: IEscrow - -Defined in: [interfaces.ts:46](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L46) - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:48](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L48) - -*** - -### amountPaid - -> **amountPaid**: `bigint` - -Defined in: [interfaces.ts:49](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L49) - -*** - -### balance - -> **balance**: `bigint` - -Defined in: [interfaces.ts:50](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L50) - -*** - -### chainId - -> **chainId**: `number` - -Defined in: [interfaces.ts:71](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L71) - -*** - -### count - -> **count**: `number` - -Defined in: [interfaces.ts:51](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L51) - -*** - -### createdAt - -> **createdAt**: `number` - -Defined in: [interfaces.ts:70](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L70) - -*** - -### exchangeOracle - -> **exchangeOracle**: `string` \| `null` - -Defined in: [interfaces.ts:63](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L63) - -*** - -### exchangeOracleFee - -> **exchangeOracleFee**: `number` \| `null` - -Defined in: [interfaces.ts:66](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L66) - -*** - -### factoryAddress - -> **factoryAddress**: `string` - -Defined in: [interfaces.ts:52](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L52) - -*** - -### finalResultsHash - -> **finalResultsHash**: `string` \| `null` - -Defined in: [interfaces.ts:54](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L54) - -*** - -### finalResultsUrl - -> **finalResultsUrl**: `string` \| `null` - -Defined in: [interfaces.ts:53](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L53) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:47](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L47) - -*** - -### intermediateResultsHash - -> **intermediateResultsHash**: `string` \| `null` - -Defined in: [interfaces.ts:56](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L56) - -*** - -### intermediateResultsUrl - -> **intermediateResultsUrl**: `string` \| `null` - -Defined in: [interfaces.ts:55](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L55) - -*** - -### jobRequesterId - -> **jobRequesterId**: `string` \| `null` - -Defined in: [interfaces.ts:58](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L58) - -*** - -### launcher - -> **launcher**: `string` - -Defined in: [interfaces.ts:57](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L57) - -*** - -### manifest - -> **manifest**: `string` \| `null` - -Defined in: [interfaces.ts:60](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L60) - -*** - -### manifestHash - -> **manifestHash**: `string` \| `null` - -Defined in: [interfaces.ts:59](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L59) - -*** - -### recordingOracle - -> **recordingOracle**: `string` \| `null` - -Defined in: [interfaces.ts:61](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L61) - -*** - -### recordingOracleFee - -> **recordingOracleFee**: `number` \| `null` - -Defined in: [interfaces.ts:64](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L64) - -*** - -### reputationOracle - -> **reputationOracle**: `string` \| `null` - -Defined in: [interfaces.ts:62](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L62) - -*** - -### reputationOracleFee - -> **reputationOracleFee**: `number` \| `null` - -Defined in: [interfaces.ts:65](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L65) - -*** - -### status - -> **status**: `string` - -Defined in: [interfaces.ts:67](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L67) - -*** - -### token - -> **token**: `string` - -Defined in: [interfaces.ts:68](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L68) - -*** - -### totalFundedAmount - -> **totalFundedAmount**: `bigint` - -Defined in: [interfaces.ts:69](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L69) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md deleted file mode 100644 index 7704b93b03..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrowConfig.md +++ /dev/null @@ -1,73 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrowConfig - -# Interface: IEscrowConfig - -Defined in: [interfaces.ts:86](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L86) - -## Properties - -### exchangeOracle - -> **exchangeOracle**: `string` - -Defined in: [interfaces.ts:89](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L89) - -*** - -### exchangeOracleFee - -> **exchangeOracleFee**: `bigint` - -Defined in: [interfaces.ts:92](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L92) - -*** - -### manifest - -> **manifest**: `string` - -Defined in: [interfaces.ts:93](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L93) - -*** - -### manifestHash - -> **manifestHash**: `string` - -Defined in: [interfaces.ts:94](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L94) - -*** - -### recordingOracle - -> **recordingOracle**: `string` - -Defined in: [interfaces.ts:87](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L87) - -*** - -### recordingOracleFee - -> **recordingOracleFee**: `bigint` - -Defined in: [interfaces.ts:90](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L90) - -*** - -### reputationOracle - -> **reputationOracle**: `string` - -Defined in: [interfaces.ts:88](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L88) - -*** - -### reputationOracleFee - -> **reputationOracleFee**: `bigint` - -Defined in: [interfaces.ts:91](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L91) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowStatistics.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowStatistics.md deleted file mode 100644 index 264b132811..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrowStatistics.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrowStatistics - -# Interface: IEscrowStatistics - -Defined in: [interfaces.ts:241](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L241) - -## Properties - -### dailyEscrowsData - -> **dailyEscrowsData**: [`IDailyEscrow`](IDailyEscrow.md)[] - -Defined in: [interfaces.ts:243](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L243) - -*** - -### totalEscrows - -> **totalEscrows**: `number` - -Defined in: [interfaces.ts:242](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L242) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowWithdraw.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowWithdraw.md deleted file mode 100644 index 81c22bcbc7..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrowWithdraw.md +++ /dev/null @@ -1,33 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrowWithdraw - -# Interface: IEscrowWithdraw - -Defined in: [interfaces.ts:310](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L310) - -## Properties - -### tokenAddress - -> **tokenAddress**: `string` - -Defined in: [interfaces.ts:312](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L312) - -*** - -### txHash - -> **txHash**: `string` - -Defined in: [interfaces.ts:311](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L311) - -*** - -### withdrawnAmount - -> **withdrawnAmount**: `bigint` - -Defined in: [interfaces.ts:313](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L313) diff --git a/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md deleted file mode 100644 index 1060470aa0..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IEscrowsFilter.md +++ /dev/null @@ -1,121 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IEscrowsFilter - -# Interface: IEscrowsFilter - -Defined in: [interfaces.ts:74](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L74) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:83](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L83) - -*** - -### exchangeOracle? - -> `optional` **exchangeOracle**: `string` - -Defined in: [interfaces.ts:78](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L78) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### from? - -> `optional` **from**: `Date` - -Defined in: [interfaces.ts:81](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L81) - -*** - -### jobRequesterId? - -> `optional` **jobRequesterId**: `string` - -Defined in: [interfaces.ts:79](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L79) - -*** - -### launcher? - -> `optional` **launcher**: `string` - -Defined in: [interfaces.ts:75](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L75) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### recordingOracle? - -> `optional` **recordingOracle**: `string` - -Defined in: [interfaces.ts:77](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L77) - -*** - -### reputationOracle? - -> `optional` **reputationOracle**: `string` - -Defined in: [interfaces.ts:76](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L76) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) - -*** - -### status? - -> `optional` **status**: [`EscrowStatus`](../../types/enumerations/EscrowStatus.md) \| [`EscrowStatus`](../../types/enumerations/EscrowStatus.md)[] - -Defined in: [interfaces.ts:80](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L80) - -*** - -### to? - -> `optional` **to**: `Date` - -Defined in: [interfaces.ts:82](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L82) diff --git a/docs/sdk/typescript/interfaces/interfaces/IHMTHolder.md b/docs/sdk/typescript/interfaces/interfaces/IHMTHolder.md deleted file mode 100644 index 51af45bfaa..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IHMTHolder.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IHMTHolder - -# Interface: IHMTHolder - -Defined in: [interfaces.ts:272](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L272) - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:273](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L273) - -*** - -### balance - -> **balance**: `bigint` - -Defined in: [interfaces.ts:274](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L274) diff --git a/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md b/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md deleted file mode 100644 index e35e8e43ae..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IHMTHoldersParams.md +++ /dev/null @@ -1,57 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IHMTHoldersParams - -# Interface: IHMTHoldersParams - -Defined in: [interfaces.ts:109](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L109) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### address? - -> `optional` **address**: `string` - -Defined in: [interfaces.ts:110](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L110) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) diff --git a/docs/sdk/typescript/interfaces/interfaces/IHMTStatistics.md b/docs/sdk/typescript/interfaces/interfaces/IHMTStatistics.md deleted file mode 100644 index 1b73821946..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IHMTStatistics.md +++ /dev/null @@ -1,33 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IHMTStatistics - -# Interface: IHMTStatistics - -Defined in: [interfaces.ts:266](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L266) - -## Properties - -### totalHolders - -> **totalHolders**: `number` - -Defined in: [interfaces.ts:269](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L269) - -*** - -### totalTransferAmount - -> **totalTransferAmount**: `bigint` - -Defined in: [interfaces.ts:267](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L267) - -*** - -### totalTransferCount - -> **totalTransferCount**: `number` - -Defined in: [interfaces.ts:268](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L268) diff --git a/docs/sdk/typescript/interfaces/interfaces/IKVStore.md b/docs/sdk/typescript/interfaces/interfaces/IKVStore.md deleted file mode 100644 index ac67cd4bd9..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IKVStore.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IKVStore - -# Interface: IKVStore - -Defined in: [interfaces.ts:121](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L121) - -## Properties - -### key - -> **key**: `string` - -Defined in: [interfaces.ts:122](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L122) - -*** - -### value - -> **value**: `string` - -Defined in: [interfaces.ts:123](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L123) diff --git a/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md b/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md deleted file mode 100644 index 3eaef5d813..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IKeyPair.md +++ /dev/null @@ -1,41 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IKeyPair - -# Interface: IKeyPair - -Defined in: [interfaces.ts:97](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L97) - -## Properties - -### passphrase - -> **passphrase**: `string` - -Defined in: [interfaces.ts:100](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L100) - -*** - -### privateKey - -> **privateKey**: `string` - -Defined in: [interfaces.ts:98](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L98) - -*** - -### publicKey - -> **publicKey**: `string` - -Defined in: [interfaces.ts:99](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L99) - -*** - -### revocationCertificate? - -> `optional` **revocationCertificate**: `string` - -Defined in: [interfaces.ts:101](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L101) diff --git a/docs/sdk/typescript/interfaces/interfaces/IOperator.md b/docs/sdk/typescript/interfaces/interfaces/IOperator.md deleted file mode 100644 index 958f25833a..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IOperator.md +++ /dev/null @@ -1,177 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IOperator - -# Interface: IOperator - -Defined in: [interfaces.ts:9](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L9) - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L12) - -*** - -### amountJobsProcessed - -> **amountJobsProcessed**: `bigint` \| `null` - -Defined in: [interfaces.ts:18](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L18) - -*** - -### category - -> **category**: `string` \| `null` - -Defined in: [interfaces.ts:30](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L30) - -*** - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:11](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L11) - -*** - -### fee - -> **fee**: `bigint` \| `null` - -Defined in: [interfaces.ts:20](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L20) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:10](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L10) - -*** - -### jobTypes - -> **jobTypes**: `string`[] \| `null` - -Defined in: [interfaces.ts:25](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L25) - -*** - -### lockedAmount - -> **lockedAmount**: `bigint` \| `null` - -Defined in: [interfaces.ts:14](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L14) - -*** - -### lockedUntilTimestamp - -> **lockedUntilTimestamp**: `number` \| `null` - -Defined in: [interfaces.ts:15](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L15) - -*** - -### name - -> **name**: `string` \| `null` - -Defined in: [interfaces.ts:29](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L29) - -*** - -### publicKey - -> **publicKey**: `string` \| `null` - -Defined in: [interfaces.ts:21](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L21) - -*** - -### registrationInstructions - -> **registrationInstructions**: `string` \| `null` - -Defined in: [interfaces.ts:27](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L27) - -*** - -### registrationNeeded - -> **registrationNeeded**: `boolean` \| `null` - -Defined in: [interfaces.ts:26](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L26) - -*** - -### reputationNetworks - -> **reputationNetworks**: `string`[] - -Defined in: [interfaces.ts:28](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L28) - -*** - -### role - -> **role**: `string` \| `null` - -Defined in: [interfaces.ts:19](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L19) - -*** - -### slashedAmount - -> **slashedAmount**: `bigint` \| `null` - -Defined in: [interfaces.ts:17](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L17) - -*** - -### stakedAmount - -> **stakedAmount**: `bigint` \| `null` - -Defined in: [interfaces.ts:13](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L13) - -*** - -### url - -> **url**: `string` \| `null` - -Defined in: [interfaces.ts:24](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L24) - -*** - -### webhookUrl - -> **webhookUrl**: `string` \| `null` - -Defined in: [interfaces.ts:22](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L22) - -*** - -### website - -> **website**: `string` \| `null` - -Defined in: [interfaces.ts:23](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L23) - -*** - -### withdrawnAmount - -> **withdrawnAmount**: `bigint` \| `null` - -Defined in: [interfaces.ts:16](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L16) diff --git a/docs/sdk/typescript/interfaces/interfaces/IOperatorsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IOperatorsFilter.md deleted file mode 100644 index 7280f6f369..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IOperatorsFilter.md +++ /dev/null @@ -1,81 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IOperatorsFilter - -# Interface: IOperatorsFilter - -Defined in: [interfaces.ts:33](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L33) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:34](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L34) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### minStakedAmount? - -> `optional` **minStakedAmount**: `number` - -Defined in: [interfaces.ts:36](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L36) - -*** - -### orderBy? - -> `optional` **orderBy**: `string` - -Defined in: [interfaces.ts:37](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L37) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### roles? - -> `optional` **roles**: `string`[] - -Defined in: [interfaces.ts:35](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L35) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPagination.md b/docs/sdk/typescript/interfaces/interfaces/IPagination.md deleted file mode 100644 index c1019d2ad3..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IPagination.md +++ /dev/null @@ -1,46 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IPagination - -# Interface: IPagination - -Defined in: [interfaces.ts:163](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L163) - -## Extended by - -- [`IOperatorsFilter`](IOperatorsFilter.md) -- [`IEscrowsFilter`](IEscrowsFilter.md) -- [`IStatisticsFilter`](IStatisticsFilter.md) -- [`IHMTHoldersParams`](IHMTHoldersParams.md) -- [`IPayoutFilter`](IPayoutFilter.md) -- [`ITransactionsFilter`](ITransactionsFilter.md) -- [`IStatusEventFilter`](IStatusEventFilter.md) -- [`IWorkersFilter`](IWorkersFilter.md) -- [`IStakersFilter`](IStakersFilter.md) -- [`ICancellationRefundFilter`](ICancellationRefundFilter.md) - -## Properties - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPaymentStatistics.md b/docs/sdk/typescript/interfaces/interfaces/IPaymentStatistics.md deleted file mode 100644 index 8c27f833ca..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IPaymentStatistics.md +++ /dev/null @@ -1,17 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IPaymentStatistics - -# Interface: IPaymentStatistics - -Defined in: [interfaces.ts:262](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L262) - -## Properties - -### dailyPaymentsData - -> **dailyPaymentsData**: [`IDailyPayment`](IDailyPayment.md)[] - -Defined in: [interfaces.ts:263](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L263) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPayout.md b/docs/sdk/typescript/interfaces/interfaces/IPayout.md deleted file mode 100644 index aea8e9ac32..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IPayout.md +++ /dev/null @@ -1,49 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IPayout - -# Interface: IPayout - -Defined in: [interfaces.ts:302](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L302) - -## Properties - -### amount - -> **amount**: `bigint` - -Defined in: [interfaces.ts:306](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L306) - -*** - -### createdAt - -> **createdAt**: `number` - -Defined in: [interfaces.ts:307](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L307) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [interfaces.ts:304](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L304) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:303](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L303) - -*** - -### recipient - -> **recipient**: `string` - -Defined in: [interfaces.ts:305](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L305) diff --git a/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md b/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md deleted file mode 100644 index 5ae548411d..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IPayoutFilter.md +++ /dev/null @@ -1,89 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IPayoutFilter - -# Interface: IPayoutFilter - -Defined in: [interfaces.ts:113](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L113) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:114](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L114) - -*** - -### escrowAddress? - -> `optional` **escrowAddress**: `string` - -Defined in: [interfaces.ts:115](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L115) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### from? - -> `optional` **from**: `Date` - -Defined in: [interfaces.ts:117](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L117) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### recipient? - -> `optional` **recipient**: `string` - -Defined in: [interfaces.ts:116](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L116) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) - -*** - -### to? - -> `optional` **to**: `Date` - -Defined in: [interfaces.ts:118](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L118) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md b/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md deleted file mode 100644 index e31e857b8f..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IReputationNetwork.md +++ /dev/null @@ -1,33 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IReputationNetwork - -# Interface: IReputationNetwork - -Defined in: [interfaces.ts:40](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L40) - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:42](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L42) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:41](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L41) - -*** - -### operators - -> **operators**: [`IOperator`](IOperator.md)[] - -Defined in: [interfaces.ts:43](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L43) diff --git a/docs/sdk/typescript/interfaces/interfaces/IReward.md b/docs/sdk/typescript/interfaces/interfaces/IReward.md deleted file mode 100644 index a88ede941c..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IReward.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IReward - -# Interface: IReward - -Defined in: [interfaces.ts:4](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L4) - -## Properties - -### amount - -> **amount**: `bigint` - -Defined in: [interfaces.ts:6](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L6) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [interfaces.ts:5](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L5) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStaker.md b/docs/sdk/typescript/interfaces/interfaces/IStaker.md deleted file mode 100644 index f93db8d21d..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IStaker.md +++ /dev/null @@ -1,65 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IStaker - -# Interface: IStaker - -Defined in: [interfaces.ts:197](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L197) - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:198](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L198) - -*** - -### lastDepositTimestamp - -> **lastDepositTimestamp**: `number` - -Defined in: [interfaces.ts:204](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L204) - -*** - -### lockedAmount - -> **lockedAmount**: `bigint` - -Defined in: [interfaces.ts:200](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L200) - -*** - -### lockedUntil - -> **lockedUntil**: `number` - -Defined in: [interfaces.ts:203](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L203) - -*** - -### slashedAmount - -> **slashedAmount**: `bigint` - -Defined in: [interfaces.ts:202](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L202) - -*** - -### stakedAmount - -> **stakedAmount**: `bigint` - -Defined in: [interfaces.ts:199](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L199) - -*** - -### withdrawableAmount - -> **withdrawableAmount**: `bigint` - -Defined in: [interfaces.ts:201](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L201) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStakersFilter.md b/docs/sdk/typescript/interfaces/interfaces/IStakersFilter.md deleted file mode 100644 index f9d3aa5a99..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IStakersFilter.md +++ /dev/null @@ -1,129 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IStakersFilter - -# Interface: IStakersFilter - -Defined in: [interfaces.ts:207](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L207) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:208](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L208) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### maxLockedAmount? - -> `optional` **maxLockedAmount**: `string` - -Defined in: [interfaces.ts:212](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L212) - -*** - -### maxSlashedAmount? - -> `optional` **maxSlashedAmount**: `string` - -Defined in: [interfaces.ts:216](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L216) - -*** - -### maxStakedAmount? - -> `optional` **maxStakedAmount**: `string` - -Defined in: [interfaces.ts:210](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L210) - -*** - -### maxWithdrawnAmount? - -> `optional` **maxWithdrawnAmount**: `string` - -Defined in: [interfaces.ts:214](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L214) - -*** - -### minLockedAmount? - -> `optional` **minLockedAmount**: `string` - -Defined in: [interfaces.ts:211](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L211) - -*** - -### minSlashedAmount? - -> `optional` **minSlashedAmount**: `string` - -Defined in: [interfaces.ts:215](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L215) - -*** - -### minStakedAmount? - -> `optional` **minStakedAmount**: `string` - -Defined in: [interfaces.ts:209](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L209) - -*** - -### minWithdrawnAmount? - -> `optional` **minWithdrawnAmount**: `string` - -Defined in: [interfaces.ts:213](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L213) - -*** - -### orderBy? - -> `optional` **orderBy**: `"stakedAmount"` \| `"lockedAmount"` \| `"withdrawnAmount"` \| `"slashedAmount"` \| `"lastDepositTimestamp"` - -Defined in: [interfaces.ts:217](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L217) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md b/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md deleted file mode 100644 index 263048e88d..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IStatisticsFilter.md +++ /dev/null @@ -1,65 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IStatisticsFilter - -# Interface: IStatisticsFilter - -Defined in: [interfaces.ts:104](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L104) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### from? - -> `optional` **from**: `Date` - -Defined in: [interfaces.ts:105](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L105) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) - -*** - -### to? - -> `optional` **to**: `Date` - -Defined in: [interfaces.ts:106](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L106) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStatusEvent.md b/docs/sdk/typescript/interfaces/interfaces/IStatusEvent.md deleted file mode 100644 index 21910c67da..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IStatusEvent.md +++ /dev/null @@ -1,41 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IStatusEvent - -# Interface: IStatusEvent - -Defined in: [interfaces.ts:285](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L285) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:289](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L289) - -*** - -### escrowAddress - -> **escrowAddress**: `string` - -Defined in: [interfaces.ts:287](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L287) - -*** - -### status - -> **status**: [`EscrowStatus`](../../types/enumerations/EscrowStatus.md) - -Defined in: [interfaces.ts:288](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L288) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:286](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L286) diff --git a/docs/sdk/typescript/interfaces/interfaces/IStatusEventFilter.md b/docs/sdk/typescript/interfaces/interfaces/IStatusEventFilter.md deleted file mode 100644 index 86b812d8d0..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IStatusEventFilter.md +++ /dev/null @@ -1,89 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IStatusEventFilter - -# Interface: IStatusEventFilter - -Defined in: [interfaces.ts:176](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L176) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:177](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L177) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### from? - -> `optional` **from**: `Date` - -Defined in: [interfaces.ts:179](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L179) - -*** - -### launcher? - -> `optional` **launcher**: `string` - -Defined in: [interfaces.ts:181](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L181) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) - -*** - -### statuses? - -> `optional` **statuses**: [`EscrowStatus`](../../types/enumerations/EscrowStatus.md)[] - -Defined in: [interfaces.ts:178](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L178) - -*** - -### to? - -> `optional` **to**: `Date` - -Defined in: [interfaces.ts:180](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L180) diff --git a/docs/sdk/typescript/interfaces/interfaces/ITransaction.md b/docs/sdk/typescript/interfaces/interfaces/ITransaction.md deleted file mode 100644 index 9481267b97..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/ITransaction.md +++ /dev/null @@ -1,97 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ITransaction - -# Interface: ITransaction - -Defined in: [interfaces.ts:136](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L136) - -## Properties - -### block - -> **block**: `bigint` - -Defined in: [interfaces.ts:137](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L137) - -*** - -### escrow - -> **escrow**: `string` \| `null` - -Defined in: [interfaces.ts:145](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L145) - -*** - -### from - -> **from**: `string` - -Defined in: [interfaces.ts:139](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L139) - -*** - -### internalTransactions - -> **internalTransactions**: [`InternalTransaction`](InternalTransaction.md)[] - -Defined in: [interfaces.ts:147](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L147) - -*** - -### method - -> **method**: `string` - -Defined in: [interfaces.ts:143](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L143) - -*** - -### receiver - -> **receiver**: `string` \| `null` - -Defined in: [interfaces.ts:144](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L144) - -*** - -### timestamp - -> **timestamp**: `number` - -Defined in: [interfaces.ts:141](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L141) - -*** - -### to - -> **to**: `string` - -Defined in: [interfaces.ts:140](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L140) - -*** - -### token - -> **token**: `string` \| `null` - -Defined in: [interfaces.ts:146](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L146) - -*** - -### txHash - -> **txHash**: `string` - -Defined in: [interfaces.ts:138](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L138) - -*** - -### value - -> **value**: `bigint` - -Defined in: [interfaces.ts:142](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L142) diff --git a/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md b/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md deleted file mode 100644 index 425de8a393..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/ITransactionsFilter.md +++ /dev/null @@ -1,129 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / ITransactionsFilter - -# Interface: ITransactionsFilter - -Defined in: [interfaces.ts:150](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L150) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:151](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L151) - -*** - -### endBlock? - -> `optional` **endBlock**: `number` - -Defined in: [interfaces.ts:153](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L153) - -*** - -### endDate? - -> `optional` **endDate**: `Date` - -Defined in: [interfaces.ts:155](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L155) - -*** - -### escrow? - -> `optional` **escrow**: `string` - -Defined in: [interfaces.ts:159](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L159) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### fromAddress? - -> `optional` **fromAddress**: `string` - -Defined in: [interfaces.ts:156](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L156) - -*** - -### method? - -> `optional` **method**: `string` - -Defined in: [interfaces.ts:158](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L158) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) - -*** - -### startBlock? - -> `optional` **startBlock**: `number` - -Defined in: [interfaces.ts:152](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L152) - -*** - -### startDate? - -> `optional` **startDate**: `Date` - -Defined in: [interfaces.ts:154](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L154) - -*** - -### toAddress? - -> `optional` **toAddress**: `string` - -Defined in: [interfaces.ts:157](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L157) - -*** - -### token? - -> `optional` **token**: `string` - -Defined in: [interfaces.ts:160](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L160) diff --git a/docs/sdk/typescript/interfaces/interfaces/IWorker.md b/docs/sdk/typescript/interfaces/interfaces/IWorker.md deleted file mode 100644 index f6bbe9d7ca..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IWorker.md +++ /dev/null @@ -1,41 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IWorker - -# Interface: IWorker - -Defined in: [interfaces.ts:184](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L184) - -## Properties - -### address - -> **address**: `string` - -Defined in: [interfaces.ts:186](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L186) - -*** - -### id - -> **id**: `string` - -Defined in: [interfaces.ts:185](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L185) - -*** - -### payoutCount - -> **payoutCount**: `number` - -Defined in: [interfaces.ts:188](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L188) - -*** - -### totalHMTAmountReceived - -> **totalHMTAmountReceived**: `bigint` - -Defined in: [interfaces.ts:187](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L187) diff --git a/docs/sdk/typescript/interfaces/interfaces/IWorkerStatistics.md b/docs/sdk/typescript/interfaces/interfaces/IWorkerStatistics.md deleted file mode 100644 index d18cbdc5a9..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IWorkerStatistics.md +++ /dev/null @@ -1,17 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IWorkerStatistics - -# Interface: IWorkerStatistics - -Defined in: [interfaces.ts:251](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L251) - -## Properties - -### dailyWorkersData - -> **dailyWorkersData**: [`IDailyWorker`](IDailyWorker.md)[] - -Defined in: [interfaces.ts:252](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L252) diff --git a/docs/sdk/typescript/interfaces/interfaces/IWorkersFilter.md b/docs/sdk/typescript/interfaces/interfaces/IWorkersFilter.md deleted file mode 100644 index 9a2f129882..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/IWorkersFilter.md +++ /dev/null @@ -1,73 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / IWorkersFilter - -# Interface: IWorkersFilter - -Defined in: [interfaces.ts:191](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L191) - -## Extends - -- [`IPagination`](IPagination.md) - -## Properties - -### address? - -> `optional` **address**: `string` - -Defined in: [interfaces.ts:193](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L193) - -*** - -### chainId - -> **chainId**: [`ChainId`](../../enums/enumerations/ChainId.md) - -Defined in: [interfaces.ts:192](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L192) - -*** - -### first? - -> `optional` **first**: `number` - -Defined in: [interfaces.ts:164](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L164) - -#### Inherited from - -[`IPagination`](IPagination.md).[`first`](IPagination.md#first) - -*** - -### orderBy? - -> `optional` **orderBy**: `string` - -Defined in: [interfaces.ts:194](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L194) - -*** - -### orderDirection? - -> `optional` **orderDirection**: [`OrderDirection`](../../enums/enumerations/OrderDirection.md) - -Defined in: [interfaces.ts:166](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L166) - -#### Inherited from - -[`IPagination`](IPagination.md).[`orderDirection`](IPagination.md#orderdirection) - -*** - -### skip? - -> `optional` **skip**: `number` - -Defined in: [interfaces.ts:165](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L165) - -#### Inherited from - -[`IPagination`](IPagination.md).[`skip`](IPagination.md#skip) diff --git a/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md b/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md deleted file mode 100644 index b55dfbfd6e..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/InternalTransaction.md +++ /dev/null @@ -1,65 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / InternalTransaction - -# Interface: InternalTransaction - -Defined in: [interfaces.ts:126](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L126) - -## Properties - -### escrow - -> **escrow**: `string` \| `null` - -Defined in: [interfaces.ts:132](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L132) - -*** - -### from - -> **from**: `string` - -Defined in: [interfaces.ts:127](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L127) - -*** - -### method - -> **method**: `string` - -Defined in: [interfaces.ts:130](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L130) - -*** - -### receiver - -> **receiver**: `string` \| `null` - -Defined in: [interfaces.ts:131](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L131) - -*** - -### to - -> **to**: `string` - -Defined in: [interfaces.ts:128](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L128) - -*** - -### token - -> **token**: `string` \| `null` - -Defined in: [interfaces.ts:133](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L133) - -*** - -### value - -> **value**: `bigint` - -Defined in: [interfaces.ts:129](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L129) diff --git a/docs/sdk/typescript/interfaces/interfaces/StakerInfo.md b/docs/sdk/typescript/interfaces/interfaces/StakerInfo.md deleted file mode 100644 index 6ae97c9b48..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/StakerInfo.md +++ /dev/null @@ -1,41 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / StakerInfo - -# Interface: StakerInfo - -Defined in: [interfaces.ts:169](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L169) - -## Properties - -### lockedAmount - -> **lockedAmount**: `bigint` - -Defined in: [interfaces.ts:171](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L171) - -*** - -### lockedUntil - -> **lockedUntil**: `bigint` - -Defined in: [interfaces.ts:172](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L172) - -*** - -### stakedAmount - -> **stakedAmount**: `bigint` - -Defined in: [interfaces.ts:170](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L170) - -*** - -### withdrawableAmount - -> **withdrawableAmount**: `bigint` - -Defined in: [interfaces.ts:173](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L173) diff --git a/docs/sdk/typescript/interfaces/interfaces/SubgraphOptions.md b/docs/sdk/typescript/interfaces/interfaces/SubgraphOptions.md deleted file mode 100644 index 4cf671b12d..0000000000 --- a/docs/sdk/typescript/interfaces/interfaces/SubgraphOptions.md +++ /dev/null @@ -1,42 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [interfaces](../README.md) / SubgraphOptions - -# Interface: SubgraphOptions - -Defined in: [interfaces.ts:319](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L319) - -Configuration options for subgraph requests with retry logic. - -## Properties - -### baseDelay? - -> `optional` **baseDelay**: `number` - -Defined in: [interfaces.ts:323](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L323) - -Base delay between retries in milliseconds - -*** - -### indexerId? - -> `optional` **indexerId**: `string` - -Defined in: [interfaces.ts:328](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L328) - -Optional indexer identifier. When provided, requests target -`{gateway}/deployments/id//indexers/id/`. - -*** - -### maxRetries? - -> `optional` **maxRetries**: `number` - -Defined in: [interfaces.ts:321](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts#L321) - -Maximum number of retry attempts diff --git a/docs/sdk/typescript/kvstore/README.md b/docs/sdk/typescript/kvstore/README.md deleted file mode 100644 index e2a5d8f801..0000000000 --- a/docs/sdk/typescript/kvstore/README.md +++ /dev/null @@ -1,12 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / kvstore - -# kvstore - -## Classes - -- [KVStoreClient](classes/KVStoreClient.md) -- [KVStoreUtils](classes/KVStoreUtils.md) diff --git a/docs/sdk/typescript/kvstore/classes/KVStoreClient.md b/docs/sdk/typescript/kvstore/classes/KVStoreClient.md deleted file mode 100644 index d27b0651c1..0000000000 --- a/docs/sdk/typescript/kvstore/classes/KVStoreClient.md +++ /dev/null @@ -1,378 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [kvstore](../README.md) / KVStoreClient - -# Class: KVStoreClient - -Defined in: [kvstore.ts:98](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L98) - -## Introduction - -This client enables performing actions on KVStore contract and obtaining information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the `runner`. -To use this client, it is recommended to initialize it using the static `build` method. - -```ts -static async build(runner: ContractRunner): Promise; -``` - -A `Signer` or a `Provider` should be passed depending on the use case of this module: - -- **Signer**: when the user wants to use this model to send transactions calling the contract functions. -- **Provider**: when the user wants to use this model to get information from the contracts or subgraph. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -### Signer - -**Using private key (backend)** - -```ts -import { KVStoreClient } from '@human-protocol/sdk'; -import { Wallet, providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const kvstoreClient = await KVStoreClient.build(signer); -``` - -**Using Wagmi (frontend)** - -```ts -import { useSigner, useChainId } from 'wagmi'; -import { KVStoreClient } from '@human-protocol/sdk'; - -const { data: signer } = useSigner(); -const kvstoreClient = await KVStoreClient.build(signer); -``` - -### Provider - -```ts -import { KVStoreClient } from '@human-protocol/sdk'; -import { providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const kvstoreClient = await KVStoreClient.build(provider); -``` - -## Extends - -- [`BaseEthersClient`](../../base/classes/BaseEthersClient.md) - -## Constructors - -### Constructor - -> **new KVStoreClient**(`runner`, `networkData`): `KVStoreClient` - -Defined in: [kvstore.ts:107](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L107) - -**KVStoreClient constructor** - -#### Parameters - -##### runner - -`ContractRunner` - -The Runner object to interact with the Ethereum network - -##### networkData - -[`NetworkData`](../../types/type-aliases/NetworkData.md) - -The network information required to connect to the KVStore contract - -#### Returns - -`KVStoreClient` - -#### Overrides - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`constructor`](../../base/classes/BaseEthersClient.md#constructor) - -## Properties - -### networkData - -> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) - -Defined in: [base.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) - -#### Inherited from - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`networkData`](../../base/classes/BaseEthersClient.md#networkdata) - -*** - -### runner - -> `protected` **runner**: `ContractRunner` - -Defined in: [base.ts:11](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) - -#### Inherited from - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`runner`](../../base/classes/BaseEthersClient.md#runner) - -## Methods - -### get() - -> **get**(`address`, `key`): `Promise`\<`string`\> - -Defined in: [kvstore.ts:308](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L308) - -Gets the value of a key-value pair in the contract. - -#### Parameters - -##### address - -`string` - -Address from which to get the key value. - -##### key - -`string` - -Key to obtain the value. - -#### Returns - -`Promise`\<`string`\> - -Value of the key. - -**Code example** - -> Need to have available stake. - -```ts -import { providers } from 'ethers'; -import { KVStoreClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const kvstoreClient = await KVStoreClient.build(provider); - -const value = await kvstoreClient.get('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', 'Role'); -``` - -*** - -### set() - -> **set**(`key`, `value`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [kvstore.ts:170](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L170) - -This function sets a key-value pair associated with the address that submits the transaction. - -#### Parameters - -##### key - -`string` - -Key of the key-value pair - -##### value - -`string` - -Value of the key-value pair - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Need to have available stake. - -```ts -import { Wallet, providers } from 'ethers'; -import { KVStoreClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const kvstoreClient = await KVStoreClient.build(signer); - -await kvstoreClient.set('Role', 'RecordingOracle'); -``` - -*** - -### setBulk() - -> **setBulk**(`keys`, `values`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [kvstore.ts:213](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L213) - -This function sets key-value pairs in bulk associated with the address that submits the transaction. - -#### Parameters - -##### keys - -`string`[] - -Array of keys (keys and value must have the same order) - -##### values - -`string`[] - -Array of values - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -> Need to have available stake. - -```ts -import { Wallet, providers } from 'ethers'; -import { KVStoreClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const kvstoreClient = await KVStoreClient.build(signer); - -const keys = ['role', 'webhook_url']; -const values = ['RecordingOracle', 'http://localhost']; -await kvstoreClient.setBulk(keys, values); -``` - -*** - -### setFileUrlAndHash() - -> **setFileUrlAndHash**(`url`, `urlKey`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [kvstore.ts:256](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L256) - -Sets a URL value for the address that submits the transaction, and its hash. - -#### Parameters - -##### url - -`string` - -URL to set - -##### urlKey - -`string` = `'url'` - -Configurable URL key. `url` by default. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { Wallet, providers } from 'ethers'; -import { KVStoreClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const kvstoreClient = await KVStoreClient.build(signer); - -await kvstoreClient.setFileUrlAndHash('example.com'); -await kvstoreClient.setFileUrlAndHash('linkedin.com/example', 'linkedin_url'); -``` - -*** - -### build() - -> `static` **build**(`runner`): `Promise`\<`KVStoreClient`\> - -Defined in: [kvstore.ts:125](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L125) - -Creates an instance of KVStoreClient from a runner. - -#### Parameters - -##### runner - -`ContractRunner` - -The Runner object to interact with the Ethereum network - -#### Returns - -`Promise`\<`KVStoreClient`\> - -- An instance of KVStoreClient - -#### Throws - -- Thrown if the provider does not exist for the provided Signer - -#### Throws - -- Thrown if the network's chainId is not supported diff --git a/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md b/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md deleted file mode 100644 index 0f3f3bd30a..0000000000 --- a/docs/sdk/typescript/kvstore/classes/KVStoreUtils.md +++ /dev/null @@ -1,270 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [kvstore](../README.md) / KVStoreUtils - -# Class: KVStoreUtils - -Defined in: [kvstore.ts:354](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L354) - -## Introduction - -Utility class for KVStore-related operations. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -### Signer - -**Using private key (backend)** - -```ts -import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - -const KVStoreAddresses = await KVStoreUtils.getKVStoreData( - ChainId.POLYGON_AMOY, - "0x1234567890123456789012345678901234567890" -); -``` - -## Constructors - -### Constructor - -> **new KVStoreUtils**(): `KVStoreUtils` - -#### Returns - -`KVStoreUtils` - -## Methods - -### get() - -> `static` **get**(`chainId`, `address`, `key`, `options?`): `Promise`\<`string`\> - -Defined in: [kvstore.ts:429](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L429) - -Gets the value of a key-value pair in the KVStore using the subgraph. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the KVStore is deployed - -##### address - -`string` - -Address from which to get the key value. - -##### key - -`string` - -Key to obtain the value. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<`string`\> - -Value of the key. - -#### Throws - -- Thrown if the network's chainId is not supported - -#### Throws - -- Thrown if the Address sent is invalid - -#### Throws - -- Thrown if the key is empty - -**Code example** - -```ts -import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - -const chainId = ChainId.POLYGON_AMOY; -const address = '0x1234567890123456789012345678901234567890'; -const key = 'role'; - -const value = await KVStoreUtils.get(chainId, address, key); -console.log(value); -``` - -*** - -### getFileUrlAndVerifyHash() - -> `static` **getFileUrlAndVerifyHash**(`chainId`, `address`, `urlKey`, `options?`): `Promise`\<`string`\> - -Defined in: [kvstore.ts:479](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L479) - -Gets the URL value of the given entity, and verifies its hash. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the KVStore is deployed - -##### address - -`string` - -Address from which to get the URL value. - -##### urlKey - -`string` = `'url'` - -Configurable URL key. `url` by default. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<`string`\> - -URL value for the given address if it exists, and the content is valid - -**Code example** - -```ts -import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - -const chainId = ChainId.POLYGON_AMOY; -const address = '0x1234567890123456789012345678901234567890'; - -const url = await KVStoreUtils.getFileUrlAndVerifyHash(chainId, address); -console.log(url); -``` - -*** - -### getKVStoreData() - -> `static` **getKVStoreData**(`chainId`, `address`, `options?`): `Promise`\<[`IKVStore`](../../interfaces/interfaces/IKVStore.md)[]\> - -Defined in: [kvstore.ts:374](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L374) - -This function returns the KVStore data for a given address. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the KVStore is deployed - -##### address - -`string` - -Address of the KVStore - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IKVStore`](../../interfaces/interfaces/IKVStore.md)[]\> - -KVStore data - -#### Throws - -- Thrown if the network's chainId is not supported - -#### Throws - -- Thrown if the Address sent is invalid - -**Code example** - -```ts -import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - -const kvStoreData = await KVStoreUtils.getKVStoreData(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890"); -console.log(kvStoreData); -``` - -*** - -### getPublicKey() - -> `static` **getPublicKey**(`chainId`, `address`, `options?`): `Promise`\<`string`\> - -Defined in: [kvstore.ts:540](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts#L540) - -Gets the public key of the given entity, and verifies its hash. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the KVStore is deployed - -##### address - -`string` - -Address from which to get the public key. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -#### Returns - -`Promise`\<`string`\> - -Public key for the given address if it exists, and the content is valid - -**Code example** - -```ts -import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - -const chainId = ChainId.POLYGON_AMOY; -const address = '0x1234567890123456789012345678901234567890'; - -const publicKey = await KVStoreUtils.getPublicKey(chainId, address); -console.log(publicKey); -``` diff --git a/docs/sdk/typescript/modules.md b/docs/sdk/typescript/modules.md deleted file mode 100644 index b36bd138ca..0000000000 --- a/docs/sdk/typescript/modules.md +++ /dev/null @@ -1,21 +0,0 @@ -[**@human-protocol/sdk**](README.md) - -*** - -# @human-protocol/sdk - -## Modules - -- [base](base/README.md) -- [encryption](encryption/README.md) -- [enums](enums/README.md) -- [escrow](escrow/README.md) -- [graphql/types](graphql/types/README.md) -- [interfaces](interfaces/README.md) -- [kvstore](kvstore/README.md) -- [operator](operator/README.md) -- [staking](staking/README.md) -- [statistics](statistics/README.md) -- [storage](storage/README.md) -- [transaction](transaction/README.md) -- [types](types/README.md) diff --git a/docs/sdk/typescript/operator/README.md b/docs/sdk/typescript/operator/README.md deleted file mode 100644 index 111fa065f0..0000000000 --- a/docs/sdk/typescript/operator/README.md +++ /dev/null @@ -1,11 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / operator - -# operator - -## Classes - -- [OperatorUtils](classes/OperatorUtils.md) diff --git a/docs/sdk/typescript/operator/classes/OperatorUtils.md b/docs/sdk/typescript/operator/classes/OperatorUtils.md deleted file mode 100644 index 5cf1517005..0000000000 --- a/docs/sdk/typescript/operator/classes/OperatorUtils.md +++ /dev/null @@ -1,198 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [operator](../README.md) / OperatorUtils - -# Class: OperatorUtils - -Defined in: [operator.ts:29](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L29) - -## Constructors - -### Constructor - -> **new OperatorUtils**(): `OperatorUtils` - -#### Returns - -`OperatorUtils` - -## Methods - -### getOperator() - -> `static` **getOperator**(`chainId`, `address`, `options?`): `Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md) \| `null`\> - -Defined in: [operator.ts:46](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L46) - -This function returns the operator data for the given address. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the operator is deployed - -##### address - -`string` - -Operator address. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md) \| `null`\> - -- Returns the operator details or null if not found. - -**Code example** - -```ts -import { OperatorUtils, ChainId } from '@human-protocol/sdk'; - -const operator = await OperatorUtils.getOperator(ChainId.POLYGON_AMOY, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getOperators() - -> `static` **getOperators**(`filter`, `options?`): `Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md)[]\> - -Defined in: [operator.ts:92](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L92) - -This function returns all the operator details of the protocol. - -#### Parameters - -##### filter - -[`IOperatorsFilter`](../../interfaces/interfaces/IOperatorsFilter.md) - -Filter for the operators. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md)[]\> - -Returns an array with all the operator details. - -**Code example** - -```ts -import { OperatorUtils, ChainId } from '@human-protocol/sdk'; - -const filter: IOperatorsFilter = { - chainId: ChainId.POLYGON -}; -const operators = await OperatorUtils.getOperators(filter); -``` - -*** - -### getReputationNetworkOperators() - -> `static` **getReputationNetworkOperators**(`chainId`, `address`, `role?`, `options?`): `Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md)[]\> - -Defined in: [operator.ts:159](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L159) - -Retrieves the reputation network operators of the specified address. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the reputation network is deployed - -##### address - -`string` - -Address of the reputation oracle. - -##### role? - -`string` - -(Optional) Role of the operator. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IOperator`](../../interfaces/interfaces/IOperator.md)[]\> - -- Returns an array of operator details. - -**Code example** - -```ts -import { OperatorUtils, ChainId } from '@human-protocol/sdk'; - -const operators = await OperatorUtils.getReputationNetworkOperators(ChainId.POLYGON_AMOY, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getRewards() - -> `static` **getRewards**(`chainId`, `slasherAddress`, `options?`): `Promise`\<[`IReward`](../../interfaces/interfaces/IReward.md)[]\> - -Defined in: [operator.ts:205](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/operator.ts#L205) - -This function returns information about the rewards for a given slasher address. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the rewards are deployed - -##### slasherAddress - -`string` - -Slasher address. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IReward`](../../interfaces/interfaces/IReward.md)[]\> - -Returns an array of Reward objects that contain the rewards earned by the user through slashing other users. - -**Code example** - -```ts -import { OperatorUtils, ChainId } from '@human-protocol/sdk'; - -const rewards = await OperatorUtils.getRewards(ChainId.POLYGON_AMOY, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` diff --git a/docs/sdk/typescript/staking/README.md b/docs/sdk/typescript/staking/README.md deleted file mode 100644 index 025e67e4d6..0000000000 --- a/docs/sdk/typescript/staking/README.md +++ /dev/null @@ -1,12 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / staking - -# staking - -## Classes - -- [StakingClient](classes/StakingClient.md) -- [StakingUtils](classes/StakingUtils.md) diff --git a/docs/sdk/typescript/staking/classes/StakingClient.md b/docs/sdk/typescript/staking/classes/StakingClient.md deleted file mode 100644 index 63d86b550b..0000000000 --- a/docs/sdk/typescript/staking/classes/StakingClient.md +++ /dev/null @@ -1,482 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [staking](../README.md) / StakingClient - -# Class: StakingClient - -Defined in: [staking.ts:108](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L108) - -## Introduction - -This client enables performing actions on staking contracts and obtaining staking information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the `runner`. -To use this client, it is recommended to initialize it using the static `build` method. - -```ts -static async build(runner: ContractRunner): Promise; -``` - -A `Signer` or a `Provider` should be passed depending on the use case of this module: - -- **Signer**: when the user wants to use this model to send transactions calling the contract functions. -- **Provider**: when the user wants to use this model to get information from the contracts or subgraph. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -### Signer - -**Using private key (backend)** - -```ts -import { StakingClient } from '@human-protocol/sdk'; -import { Wallet, providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); -``` - -**Using Wagmi (frontend)** - -```ts -import { useSigner, useChainId } from 'wagmi'; -import { StakingClient } from '@human-protocol/sdk'; - -const { data: signer } = useSigner(); -const stakingClient = await StakingClient.build(signer); -``` - -### Provider - -```ts -import { StakingClient } from '@human-protocol/sdk'; -import { providers } from 'ethers'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const stakingClient = await StakingClient.build(provider); -``` - -## Extends - -- [`BaseEthersClient`](../../base/classes/BaseEthersClient.md) - -## Constructors - -### Constructor - -> **new StakingClient**(`runner`, `networkData`): `StakingClient` - -Defined in: [staking.ts:119](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L119) - -**StakingClient constructor** - -#### Parameters - -##### runner - -`ContractRunner` - -The Runner object to interact with the Ethereum network - -##### networkData - -[`NetworkData`](../../types/type-aliases/NetworkData.md) - -The network information required to connect to the Staking contract - -#### Returns - -`StakingClient` - -#### Overrides - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`constructor`](../../base/classes/BaseEthersClient.md#constructor) - -## Properties - -### escrowFactoryContract - -> **escrowFactoryContract**: `EscrowFactory` - -Defined in: [staking.ts:111](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L111) - -*** - -### networkData - -> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) - -Defined in: [base.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L12) - -#### Inherited from - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`networkData`](../../base/classes/BaseEthersClient.md#networkdata) - -*** - -### runner - -> `protected` **runner**: `ContractRunner` - -Defined in: [base.ts:11](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/base.ts#L11) - -#### Inherited from - -[`BaseEthersClient`](../../base/classes/BaseEthersClient.md).[`runner`](../../base/classes/BaseEthersClient.md#runner) - -*** - -### stakingContract - -> **stakingContract**: `Staking` - -Defined in: [staking.ts:110](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L110) - -*** - -### tokenContract - -> **tokenContract**: `HMToken` - -Defined in: [staking.ts:109](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L109) - -## Methods - -### approveStake() - -> **approveStake**(`amount`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [staking.ts:204](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L204) - -This function approves the staking contract to transfer a specified amount of tokens when the user stakes. It increases the allowance for the staking contract. - -#### Parameters - -##### amount - -`bigint` - -Amount in WEI of tokens to approve for stake. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI -await stakingClient.approveStake(amount); -``` - -*** - -### getStakerInfo() - -> **getStakerInfo**(`stakerAddress`): `Promise`\<[`StakerInfo`](../../interfaces/interfaces/StakerInfo.md)\> - -Defined in: [staking.ts:446](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L446) - -Retrieves comprehensive staking information for a staker. - -#### Parameters - -##### stakerAddress - -`string` - -The address of the staker. - -#### Returns - -`Promise`\<[`StakerInfo`](../../interfaces/interfaces/StakerInfo.md)\> - -**Code example** - -```ts -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const stakingClient = await StakingClient.build(provider); - -const stakingInfo = await stakingClient.getStakerInfo('0xYourStakerAddress'); -console.log(stakingInfo.tokensStaked); -``` - -*** - -### slash() - -> **slash**(`slasher`, `staker`, `escrowAddress`, `amount`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [staking.ts:384](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L384) - -This function reduces the allocated amount by a staker in an escrow and transfers those tokens to the reward pool. This allows the slasher to claim them later. - -#### Parameters - -##### slasher - -`string` - -Wallet address from who requested the slash - -##### staker - -`string` - -Wallet address from who is going to be slashed - -##### escrowAddress - -`string` - -Address of the escrow that the slash is made - -##### amount - -`bigint` - -Amount in WEI of tokens to slash. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI -await stakingClient.slash('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); -``` - -*** - -### stake() - -> **stake**(`amount`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [staking.ts:258](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L258) - -This function stakes a specified amount of tokens on a specific network. - -> `approveStake` must be called before - -#### Parameters - -##### amount - -`bigint` - -Amount in WEI of tokens to stake. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI -await stakingClient.approveStake(amount); // if it was already approved before, this is not necessary -await stakingClient.stake(amount); -``` - -*** - -### unstake() - -> **unstake**(`amount`, `txOptions?`): `Promise`\<`void`\> - -Defined in: [staking.ts:302](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L302) - -This function unstakes tokens from staking contract. The unstaked tokens stay locked for a period of time. - -> Must have tokens available to unstake - -#### Parameters - -##### amount - -`bigint` - -Amount in WEI of tokens to unstake. - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { ethers, Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI -await stakingClient.unstake(amount); -``` - -*** - -### withdraw() - -> **withdraw**(`txOptions?`): `Promise`\<`void`\> - -Defined in: [staking.ts:347](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L347) - -This function withdraws unstaked and non-locked tokens from staking contract to the user wallet. - -> Must have tokens available to withdraw - -#### Parameters - -##### txOptions? - -`Overrides` = `{}` - -Additional transaction parameters (optional, defaults to an empty object). - -#### Returns - -`Promise`\<`void`\> - -Returns void if successful. Throws error if any. - -**Code example** - -```ts -import { Wallet, providers } from 'ethers'; -import { StakingClient } from '@human-protocol/sdk'; - -const rpcUrl = 'YOUR_RPC_URL'; -const privateKey = 'YOUR_PRIVATE_KEY'; - -const provider = new providers.JsonRpcProvider(rpcUrl); -const signer = new Wallet(privateKey, provider); -const stakingClient = await StakingClient.build(signer); - -await stakingClient.withdraw(); -``` - -*** - -### build() - -> `static` **build**(`runner`): `Promise`\<`StakingClient`\> - -Defined in: [staking.ts:147](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L147) - -Creates an instance of StakingClient from a Runner. - -#### Parameters - -##### runner - -`ContractRunner` - -The Runner object to interact with the Ethereum network - -#### Returns - -`Promise`\<`StakingClient`\> - -- An instance of StakingClient - -#### Throws - -- Thrown if the provider does not exist for the provided Signer - -#### Throws - -- Thrown if the network's chainId is not supported diff --git a/docs/sdk/typescript/staking/classes/StakingUtils.md b/docs/sdk/typescript/staking/classes/StakingUtils.md deleted file mode 100644 index 7d60d0498a..0000000000 --- a/docs/sdk/typescript/staking/classes/StakingUtils.md +++ /dev/null @@ -1,87 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [staking](../README.md) / StakingUtils - -# Class: StakingUtils - -Defined in: [staking.ts:484](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L484) - -Utility class for Staking-related subgraph queries. - -## Constructors - -### Constructor - -> **new StakingUtils**(): `StakingUtils` - -#### Returns - -`StakingUtils` - -## Methods - -### getStaker() - -> `static` **getStaker**(`chainId`, `stakerAddress`, `options?`): `Promise`\<[`IStaker`](../../interfaces/interfaces/IStaker.md)\> - -Defined in: [staking.ts:493](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L493) - -Gets staking info for a staker from the subgraph. - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -Network in which the staking contract is deployed - -##### stakerAddress - -`string` - -Address of the staker - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IStaker`](../../interfaces/interfaces/IStaker.md)\> - -Staker info from subgraph - -*** - -### getStakers() - -> `static` **getStakers**(`filter`, `options?`): `Promise`\<[`IStaker`](../../interfaces/interfaces/IStaker.md)[]\> - -Defined in: [staking.ts:528](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/staking.ts#L528) - -Gets all stakers from the subgraph with filters, pagination and ordering. - -#### Parameters - -##### filter - -[`IStakersFilter`](../../interfaces/interfaces/IStakersFilter.md) - -Stakers filter with pagination and ordering - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IStaker`](../../interfaces/interfaces/IStaker.md)[]\> - -Array of stakers diff --git a/docs/sdk/typescript/statistics/README.md b/docs/sdk/typescript/statistics/README.md deleted file mode 100644 index e40888e983..0000000000 --- a/docs/sdk/typescript/statistics/README.md +++ /dev/null @@ -1,11 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / statistics - -# statistics - -## Classes - -- [StatisticsClient](classes/StatisticsClient.md) diff --git a/docs/sdk/typescript/statistics/classes/StatisticsClient.md b/docs/sdk/typescript/statistics/classes/StatisticsClient.md deleted file mode 100644 index 67b75646e3..0000000000 --- a/docs/sdk/typescript/statistics/classes/StatisticsClient.md +++ /dev/null @@ -1,474 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [statistics](../README.md) / StatisticsClient - -# Class: StatisticsClient - -Defined in: [statistics.ts:64](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L64) - -## Introduction - -This client enables obtaining statistical information from the subgraph. - -Unlike other SDK clients, `StatisticsClient` does not require `signer` or `provider` to be provided. -We just need to create a client object using relevant network data. - -```ts -constructor(network: NetworkData) -``` - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); -``` - -## Constructors - -### Constructor - -> **new StatisticsClient**(`networkData`): `StatisticsClient` - -Defined in: [statistics.ts:73](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L73) - -**StatisticsClient constructor** - -#### Parameters - -##### networkData - -[`NetworkData`](../../types/type-aliases/NetworkData.md) - -The network information required to connect to the Statistics contract - -#### Returns - -`StatisticsClient` - -## Properties - -### networkData - -> **networkData**: [`NetworkData`](../../types/type-aliases/NetworkData.md) - -Defined in: [statistics.ts:65](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L65) - -*** - -### subgraphUrl - -> **subgraphUrl**: `string` - -Defined in: [statistics.ts:66](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L66) - -## Methods - -### getEscrowStatistics() - -> **getEscrowStatistics**(`filter`, `options?`): `Promise`\<[`IEscrowStatistics`](../../interfaces/interfaces/IEscrowStatistics.md)\> - -Defined in: [statistics.ts:127](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L127) - -This function returns the statistical data of escrows. - -**Input parameters** - -```ts -interface IStatisticsFilter { - from?: Date; - to?: Date; - first?: number; // (Optional) Number of transactions per page. Default is 10. - skip?: number; // (Optional) Number of transactions to skip. Default is 0. - orderDirection?: OrderDirection; // (Optional) Order of the results. Default is ASC. -} -``` - -```ts -interface IDailyEscrow { - timestamp: number; - escrowsTotal: number; - escrowsPending: number; - escrowsSolved: number; - escrowsPaid: number; - escrowsCancelled: number; -}; - -interface IEscrowStatistics { - totalEscrows: number; - dailyEscrowsData: IDailyEscrow[]; -}; -``` - -#### Parameters - -##### filter - -[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` - -Statistics params with duration data - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IEscrowStatistics`](../../interfaces/interfaces/IEscrowStatistics.md)\> - -Escrow statistics data. - -**Code example** - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - -const escrowStatistics = await statisticsClient.getEscrowStatistics(); -const escrowStatisticsApril = await statisticsClient.getEscrowStatistics({ - from: new Date('2021-04-01'), - to: new Date('2021-04-30'), -}); -``` - -*** - -### getHMTDailyData() - -> **getHMTDailyData**(`filter`, `options?`): `Promise`\<[`IDailyHMT`](../../interfaces/interfaces/IDailyHMT.md)[]\> - -Defined in: [statistics.ts:510](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L510) - -This function returns the statistical data of HMToken day by day. - -**Input parameters** - -```ts -interface IStatisticsFilter { - from?: Date; - to?: Date; - first?: number; // (Optional) Number of transactions per page. Default is 10. - skip?: number; // (Optional) Number of transactions to skip. Default is 0. - orderDirection?: OrderDirection; // (Optional) Order of the results. Default is ASC. -} -``` - -```ts -interface IDailyHMT { - timestamp: number; - totalTransactionAmount: bigint; - totalTransactionCount: number; - dailyUniqueSenders: number; - dailyUniqueReceivers: number; -} -``` - -#### Parameters - -##### filter - -[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` - -Statistics params with duration data - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IDailyHMT`](../../interfaces/interfaces/IDailyHMT.md)[]\> - -Daily HMToken statistics data. - -**Code example** - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - -const dailyHMTStats = await statisticsClient.getHMTStatistics(); - -console.log('Daily HMT statistics:', dailyHMTStats); - -const hmtStatisticsRange = await statisticsClient.getHMTStatistics({ - from: new Date(2023, 4, 8), - to: new Date(2023, 5, 8), -}); - -console.log('HMT statistics from 5/8 - 6/8:', hmtStatisticsRange); -``` - -*** - -### getHMTHolders() - -> **getHMTHolders**(`params`, `options?`): `Promise`\<[`IHMTHolder`](../../interfaces/interfaces/IHMTHolder.md)[]\> - -Defined in: [statistics.ts:434](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L434) - -This function returns the holders of the HMToken with optional filters and ordering. - -**Input parameters** - -#### Parameters - -##### params - -[`IHMTHoldersParams`](../../interfaces/interfaces/IHMTHoldersParams.md) = `{}` - -HMT Holders params with filters and ordering - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IHMTHolder`](../../interfaces/interfaces/IHMTHolder.md)[]\> - -List of HMToken holders. - -**Code example** - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - -const hmtHolders = await statisticsClient.getHMTHolders({ - orderDirection: 'asc', -}); - -console.log('HMT holders:', hmtHolders.map((h) => ({ - ...h, - balance: h.balance.toString(), -}))); -``` - -*** - -### getHMTStatistics() - -> **getHMTStatistics**(`options?`): `Promise`\<[`IHMTStatistics`](../../interfaces/interfaces/IHMTStatistics.md)\> - -Defined in: [statistics.ts:392](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L392) - -This function returns the statistical data of HMToken. - -```ts -interface IHMTStatistics { - totalTransferAmount: bigint; - totalTransferCount: number; - totalHolders: number; -}; -``` - -#### Parameters - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IHMTStatistics`](../../interfaces/interfaces/IHMTStatistics.md)\> - -HMToken statistics data. - -**Code example** - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - -const hmtStatistics = await statisticsClient.getHMTStatistics(); - -console.log('HMT statistics:', { - ...hmtStatistics, - totalTransferAmount: hmtStatistics.totalTransferAmount.toString(), -}); -``` - -*** - -### getPaymentStatistics() - -> **getPaymentStatistics**(`filter`, `options?`): `Promise`\<[`IPaymentStatistics`](../../interfaces/interfaces/IPaymentStatistics.md)\> - -Defined in: [statistics.ts:321](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L321) - -This function returns the statistical data of payments. - -**Input parameters** - -```ts -interface IStatisticsFilter { - from?: Date; - to?: Date; - first?: number; // (Optional) Number of transactions per page. Default is 10. - skip?: number; // (Optional) Number of transactions to skip. Default is 0. - orderDirection?: OrderDirection; // (Optional) Order of the results. Default is ASC. -} -``` - -```ts -interface IDailyPayment { - timestamp: number; - totalAmountPaid: bigint; - totalCount: number; - averageAmountPerWorker: bigint; -}; - -interface IPaymentStatistics { - dailyPaymentsData: IDailyPayment[]; -}; -``` - -#### Parameters - -##### filter - -[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` - -Statistics params with duration data - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IPaymentStatistics`](../../interfaces/interfaces/IPaymentStatistics.md)\> - -Payment statistics data. - -**Code example** - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - -console.log( - 'Payment statistics:', - (await statisticsClient.getPaymentStatistics()).dailyPaymentsData.map( - (p) => ({ - ...p, - totalAmountPaid: p.totalAmountPaid.toString(), - averageAmountPerJob: p.averageAmountPerJob.toString(), - averageAmountPerWorker: p.averageAmountPerWorker.toString(), - }) - ) -); - -console.log( - 'Payment statistics from 5/8 - 6/8:', - ( - await statisticsClient.getPaymentStatistics({ - from: new Date(2023, 4, 8), - to: new Date(2023, 5, 8), - }) - ).dailyPaymentsData.map((p) => ({ - ...p, - totalAmountPaid: p.totalAmountPaid.toString(), - averageAmountPerJob: p.averageAmountPerJob.toString(), - averageAmountPerWorker: p.averageAmountPerWorker.toString(), - })) -); -``` - -*** - -### getWorkerStatistics() - -> **getWorkerStatistics**(`filter`, `options?`): `Promise`\<[`IWorkerStatistics`](../../interfaces/interfaces/IWorkerStatistics.md)\> - -Defined in: [statistics.ts:218](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts#L218) - -This function returns the statistical data of workers. - -**Input parameters** - -```ts -interface IStatisticsFilter { - from?: Date; - to?: Date; - first?: number; // (Optional) Number of transactions per page. Default is 10. - skip?: number; // (Optional) Number of transactions to skip. Default is 0. - orderDirection?: OrderDirection; // (Optional) Order of the results. Default is ASC. -} -``` - -```ts -interface IDailyWorker { - timestamp: number; - activeWorkers: number; -}; - -interface IWorkerStatistics { - dailyWorkersData: IDailyWorker[]; -}; -``` - -#### Parameters - -##### filter - -[`IStatisticsFilter`](../../interfaces/interfaces/IStatisticsFilter.md) = `{}` - -Statistics params with duration data - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`IWorkerStatistics`](../../interfaces/interfaces/IWorkerStatistics.md)\> - -Worker statistics data. - -**Code example** - -```ts -import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - -const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - -const workerStatistics = await statisticsClient.getWorkerStatistics(); -const workerStatisticsApril = await statisticsClient.getWorkerStatistics({ - from: new Date('2021-04-01'), - to: new Date('2021-04-30'), -}); -``` diff --git a/docs/sdk/typescript/storage/README.md b/docs/sdk/typescript/storage/README.md deleted file mode 100644 index c36d3267b7..0000000000 --- a/docs/sdk/typescript/storage/README.md +++ /dev/null @@ -1,11 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / storage - -# storage - -## Classes - -- [~~StorageClient~~](classes/StorageClient.md) diff --git a/docs/sdk/typescript/storage/classes/StorageClient.md b/docs/sdk/typescript/storage/classes/StorageClient.md deleted file mode 100644 index f50a29d10d..0000000000 --- a/docs/sdk/typescript/storage/classes/StorageClient.md +++ /dev/null @@ -1,305 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [storage](../README.md) / StorageClient - -# ~~Class: StorageClient~~ - -Defined in: [storage.ts:63](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L63) - -## Deprecated - -StorageClient is deprecated. Use Minio.Client directly. - -## Introduction - -This client enables interacting with S3 cloud storage services like Amazon S3 Bucket, Google Cloud Storage, and others. - -The instance creation of `StorageClient` should be made using its constructor: - -```ts -constructor(params: StorageParams, credentials?: StorageCredentials) -``` - -> If credentials are not provided, it uses anonymous access to the bucket for downloading files. - -## Installation - -### npm -```bash -npm install @human-protocol/sdk -``` - -### yarn -```bash -yarn install @human-protocol/sdk -``` - -## Code example - -```ts -import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - -const credentials: StorageCredentials = { - accessKey: 'ACCESS_KEY', - secretKey: 'SECRET_KEY', -}; -const params: StorageParams = { - endPoint: 'http://localhost', - port: 9000, - useSSL: false, - region: 'us-east-1' -}; - -const storageClient = new StorageClient(params, credentials); -``` - -## Constructors - -### Constructor - -> **new StorageClient**(`params`, `credentials?`): `StorageClient` - -Defined in: [storage.ts:73](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L73) - -**Storage client constructor** - -#### Parameters - -##### params - -[`StorageParams`](../../types/type-aliases/StorageParams.md) - -Cloud storage params - -##### credentials? - -[`StorageCredentials`](../../types/type-aliases/StorageCredentials.md) - -Optional. Cloud storage access data. If credentials are not provided - use anonymous access to the bucket - -#### Returns - -`StorageClient` - -## Methods - -### ~~bucketExists()~~ - -> **bucketExists**(`bucket`): `Promise`\<`boolean`\> - -Defined in: [storage.ts:262](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L262) - -This function checks if a bucket exists. - -#### Parameters - -##### bucket - -`string` - -Bucket name. - -#### Returns - -`Promise`\<`boolean`\> - -Returns `true` if exists, `false` if it doesn't. - -**Code example** - -```ts -import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - -const credentials: StorageCredentials = { - accessKey: 'ACCESS_KEY', - secretKey: 'SECRET_KEY', -}; -const params: StorageParams = { - endPoint: 'http://localhost', - port: 9000, - useSSL: false, - region: 'us-east-1' -}; - -const storageClient = new StorageClient(params, credentials); -const exists = await storageClient.bucketExists('bucket-name'); -``` - -*** - -### ~~downloadFiles()~~ - -> **downloadFiles**(`keys`, `bucket`): `Promise`\<`any`[]\> - -Defined in: [storage.ts:112](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L112) - -This function downloads files from a bucket. - -#### Parameters - -##### keys - -`string`[] - -Array of filenames to download. - -##### bucket - -`string` - -Bucket name. - -#### Returns - -`Promise`\<`any`[]\> - -Returns an array of JSON files downloaded and parsed into objects. - -**Code example** - -```ts -import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - -const params: StorageParams = { - endPoint: 'http://localhost', - port: 9000, - useSSL: false, - region: 'us-east-1' -}; - -const storageClient = new StorageClient(params); - -const keys = ['file1.json', 'file2.json']; -const files = await storageClient.downloadFiles(keys, 'bucket-name'); -``` - -*** - -### ~~listObjects()~~ - -> **listObjects**(`bucket`): `Promise`\<`string`[]\> - -Defined in: [storage.ts:292](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L292) - -This function lists all file names contained in the bucket. - -#### Parameters - -##### bucket - -`string` - -Bucket name. - -#### Returns - -`Promise`\<`string`[]\> - -Returns the list of file names contained in the bucket. - -**Code example** - -```ts -import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - -const credentials: StorageCredentials = { - accessKey: 'ACCESS_KEY', - secretKey: 'SECRET_KEY', -}; -const params: StorageParams = { - endPoint: 'http://localhost', - port: 9000, - useSSL: false, - region: 'us-east-1' -}; - -const storageClient = new StorageClient(params, credentials); -const fileNames = await storageClient.listObjects('bucket-name'); -``` - -*** - -### ~~uploadFiles()~~ - -> **uploadFiles**(`files`, `bucket`): `Promise`\<[`UploadFile`](../../types/type-aliases/UploadFile.md)[]\> - -Defined in: [storage.ts:198](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L198) - -This function uploads files to a bucket. - -#### Parameters - -##### files - -`any`[] - -Array of objects to upload serialized into JSON. - -##### bucket - -`string` - -Bucket name. - -#### Returns - -`Promise`\<[`UploadFile`](../../types/type-aliases/UploadFile.md)[]\> - -Returns an array of uploaded file metadata. - -**Code example** - -```ts -import { StorageClient, StorageCredentials, StorageParams } from '@human-protocol/sdk'; - -const credentials: StorageCredentials = { - accessKey: 'ACCESS_KEY', - secretKey: 'SECRET_KEY', -}; -const params: StorageParams = { - endPoint: 'http://localhost', - port: 9000, - useSSL: false, - region: 'us-east-1' -}; - -const storageClient = new StorageClient(params, credentials); -const file1 = { name: 'file1', description: 'description of file1' }; -const file2 = { name: 'file2', description: 'description of file2' }; -const files = [file1, file2]; -const uploadedFiles = await storageClient.uploadFiles(files, 'bucket-name'); -``` - -*** - -### ~~downloadFileFromUrl()~~ - -> `static` **downloadFileFromUrl**(`url`): `Promise`\<`any`\> - -Defined in: [storage.ts:146](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/storage.ts#L146) - -This function downloads files from a URL. - -#### Parameters - -##### url - -`string` - -URL of the file to download. - -#### Returns - -`Promise`\<`any`\> - -Returns the JSON file downloaded and parsed into an object. - -**Code example** - -```ts -import { StorageClient } from '@human-protocol/sdk'; - -const file = await StorageClient.downloadFileFromUrl('http://localhost/file.json'); -``` diff --git a/docs/sdk/typescript/transaction/README.md b/docs/sdk/typescript/transaction/README.md deleted file mode 100644 index 23e8276725..0000000000 --- a/docs/sdk/typescript/transaction/README.md +++ /dev/null @@ -1,11 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / transaction - -# transaction - -## Classes - -- [TransactionUtils](classes/TransactionUtils.md) diff --git a/docs/sdk/typescript/transaction/classes/TransactionUtils.md b/docs/sdk/typescript/transaction/classes/TransactionUtils.md deleted file mode 100644 index 5bf2a6d329..0000000000 --- a/docs/sdk/typescript/transaction/classes/TransactionUtils.md +++ /dev/null @@ -1,184 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [transaction](../README.md) / TransactionUtils - -# Class: TransactionUtils - -Defined in: [transaction.ts:22](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L22) - -## Constructors - -### Constructor - -> **new TransactionUtils**(): `TransactionUtils` - -#### Returns - -`TransactionUtils` - -## Methods - -### getTransaction() - -> `static` **getTransaction**(`chainId`, `hash`, `options?`): `Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md) \| `null`\> - -Defined in: [transaction.ts:67](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L67) - -This function returns the transaction data for the given hash. - -```ts -type ITransaction = { - block: bigint; - txHash: string; - from: string; - to: string; - timestamp: bigint; - value: bigint; - method: string; - receiver?: string; - escrow?: string; - token?: string; - internalTransactions: InternalTransaction[]; -}; -``` - -```ts -type InternalTransaction = { - from: string; - to: string; - value: bigint; - method: string; - receiver?: string; - escrow?: string; - token?: string; -}; -``` - -#### Parameters - -##### chainId - -[`ChainId`](../../enums/enumerations/ChainId.md) - -The chain ID. - -##### hash - -`string` - -The transaction hash. - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -Optional configuration for subgraph requests. - -#### Returns - -`Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md) \| `null`\> - -- Returns the transaction details or null if not found. - -**Code example** - -```ts -import { TransactionUtils, ChainId } from '@human-protocol/sdk'; - -const transaction = await TransactionUtils.getTransaction(ChainId.POLYGON, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); -``` - -*** - -### getTransactions() - -> `static` **getTransactions**(`filter`, `options?`): `Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md)[]\> - -Defined in: [transaction.ts:169](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts#L169) - -This function returns all transaction details based on the provided filter. - -> This uses Subgraph - -**Input parameters** - -```ts -interface ITransactionsFilter { - chainId: ChainId; // List of chain IDs to query. - fromAddress?: string; // (Optional) The address from which transactions are sent. - toAddress?: string; // (Optional) The address to which transactions are sent. - method?: string; // (Optional) The method of the transaction to filter by. - escrow?: string; // (Optional) The escrow address to filter transactions. - token?: string; // (Optional) The token address to filter transactions. - startDate?: Date; // (Optional) The start date to filter transactions (inclusive). - endDate?: Date; // (Optional) The end date to filter transactions (inclusive). - startBlock?: number; // (Optional) The start block number to filter transactions (inclusive). - endBlock?: number; // (Optional) The end block number to filter transactions (inclusive). - first?: number; // (Optional) Number of transactions per page. Default is 10. - skip?: number; // (Optional) Number of transactions to skip. Default is 0. - orderDirection?: OrderDirection; // (Optional) Order of the results. Default is DESC. -} - -```ts -type InternalTransaction = { - from: string; - to: string; - value: bigint; - method: string; - receiver?: string; - escrow?: string; - token?: string; -}; -``` - -```ts -type ITransaction = { - block: bigint; - txHash: string; - from: string; - to: string; - timestamp: bigint; - value: bigint; - method: string; - receiver?: string; - escrow?: string; - token?: string; - internalTransactions: InternalTransaction[]; -}; -``` - -@param {ITransactionsFilter} filter Filter for the transactions. -@param {SubgraphOptions} options Optional configuration for subgraph requests. -@returns {Promise} Returns an array with all the transaction details. - -**Code example** - -```ts -import { TransactionUtils, ChainId, OrderDirection } from '@human-protocol/sdk'; - -const filter: ITransactionsFilter = { - chainId: ChainId.POLYGON, - startDate: new Date('2022-01-01'), - endDate: new Date('2022-12-31'), - first: 10, - skip: 0, - orderDirection: OrderDirection.DESC, -}; -const transactions = await TransactionUtils.getTransactions(filter); -``` - -#### Parameters - -##### filter - -[`ITransactionsFilter`](../../interfaces/interfaces/ITransactionsFilter.md) - -##### options? - -[`SubgraphOptions`](../../interfaces/interfaces/SubgraphOptions.md) - -#### Returns - -`Promise`\<[`ITransaction`](../../interfaces/interfaces/ITransaction.md)[]\> diff --git a/docs/sdk/typescript/types/README.md b/docs/sdk/typescript/types/README.md deleted file mode 100644 index aad778dd0b..0000000000 --- a/docs/sdk/typescript/types/README.md +++ /dev/null @@ -1,19 +0,0 @@ -[**@human-protocol/sdk**](../README.md) - -*** - -[@human-protocol/sdk](../modules.md) / types - -# types - -## Enumerations - -- [EscrowStatus](enumerations/EscrowStatus.md) - -## Type Aliases - -- [NetworkData](type-aliases/NetworkData.md) -- [~~StorageCredentials~~](type-aliases/StorageCredentials.md) -- [~~StorageParams~~](type-aliases/StorageParams.md) -- [TransactionLikeWithNonce](type-aliases/TransactionLikeWithNonce.md) -- [UploadFile](type-aliases/UploadFile.md) diff --git a/docs/sdk/typescript/types/enumerations/EscrowStatus.md b/docs/sdk/typescript/types/enumerations/EscrowStatus.md deleted file mode 100644 index 65a776ba14..0000000000 --- a/docs/sdk/typescript/types/enumerations/EscrowStatus.md +++ /dev/null @@ -1,81 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [types](../README.md) / EscrowStatus - -# Enumeration: EscrowStatus - -Defined in: [types.ts:8](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L8) - -Enum for escrow statuses. - -## Enumeration Members - -### Cancelled - -> **Cancelled**: `5` - -Defined in: [types.ts:32](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L32) - -Escrow is cancelled. - -*** - -### Complete - -> **Complete**: `4` - -Defined in: [types.ts:28](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L28) - -Escrow is finished. - -*** - -### Launched - -> **Launched**: `0` - -Defined in: [types.ts:12](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L12) - -Escrow is launched. - -*** - -### Paid - -> **Paid**: `3` - -Defined in: [types.ts:24](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L24) - -Escrow is fully paid. - -*** - -### Partial - -> **Partial**: `2` - -Defined in: [types.ts:20](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L20) - -Escrow is partially paid out. - -*** - -### Pending - -> **Pending**: `1` - -Defined in: [types.ts:16](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L16) - -Escrow is funded, and waiting for the results to be submitted. - -*** - -### ToCancel - -> **ToCancel**: `6` - -Defined in: [types.ts:36](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L36) - -Escrow is cancelled. diff --git a/docs/sdk/typescript/types/type-aliases/NetworkData.md b/docs/sdk/typescript/types/type-aliases/NetworkData.md deleted file mode 100644 index b3868ee662..0000000000 --- a/docs/sdk/typescript/types/type-aliases/NetworkData.md +++ /dev/null @@ -1,123 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [types](../README.md) / NetworkData - -# Type Alias: NetworkData - -> **NetworkData** = `object` - -Defined in: [types.ts:99](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L99) - -Network data - -## Properties - -### chainId - -> **chainId**: `number` - -Defined in: [types.ts:103](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L103) - -Network chain id - -*** - -### factoryAddress - -> **factoryAddress**: `string` - -Defined in: [types.ts:119](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L119) - -Escrow Factory contract address - -*** - -### hmtAddress - -> **hmtAddress**: `string` - -Defined in: [types.ts:115](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L115) - -HMT Token contract address - -*** - -### kvstoreAddress - -> **kvstoreAddress**: `string` - -Defined in: [types.ts:127](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L127) - -KVStore contract address - -*** - -### oldFactoryAddress - -> **oldFactoryAddress**: `string` - -Defined in: [types.ts:143](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L143) - -Old Escrow Factory contract address - -*** - -### oldSubgraphUrl - -> **oldSubgraphUrl**: `string` - -Defined in: [types.ts:139](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L139) - -Old subgraph URL - -*** - -### scanUrl - -> **scanUrl**: `string` - -Defined in: [types.ts:111](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L111) - -Network scanner URL - -*** - -### stakingAddress - -> **stakingAddress**: `string` - -Defined in: [types.ts:123](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L123) - -Staking contract address - -*** - -### subgraphUrl - -> **subgraphUrl**: `string` - -Defined in: [types.ts:131](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L131) - -Subgraph URL - -*** - -### subgraphUrlApiKey - -> **subgraphUrlApiKey**: `string` - -Defined in: [types.ts:135](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L135) - -Subgraph URL API key - -*** - -### title - -> **title**: `string` - -Defined in: [types.ts:107](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L107) - -Network title diff --git a/docs/sdk/typescript/types/type-aliases/StorageCredentials.md b/docs/sdk/typescript/types/type-aliases/StorageCredentials.md deleted file mode 100644 index 628674af66..0000000000 --- a/docs/sdk/typescript/types/type-aliases/StorageCredentials.md +++ /dev/null @@ -1,37 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [types](../README.md) / StorageCredentials - -# ~~Type Alias: StorageCredentials~~ - -> `readonly` **StorageCredentials** = `object` - -Defined in: [types.ts:44](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L44) - -AWS/GCP cloud storage access data - -## Deprecated - -StorageClient is deprecated. Use Minio.Client directly. - -## Properties - -### ~~accessKey~~ - -> **accessKey**: `string` - -Defined in: [types.ts:48](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L48) - -Access Key - -*** - -### ~~secretKey~~ - -> **secretKey**: `string` - -Defined in: [types.ts:52](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L52) - -Secret Key diff --git a/docs/sdk/typescript/types/type-aliases/StorageParams.md b/docs/sdk/typescript/types/type-aliases/StorageParams.md deleted file mode 100644 index 188ee87bd4..0000000000 --- a/docs/sdk/typescript/types/type-aliases/StorageParams.md +++ /dev/null @@ -1,55 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [types](../README.md) / StorageParams - -# ~~Type Alias: StorageParams~~ - -> **StorageParams** = `object` - -Defined in: [types.ts:58](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L58) - -## Deprecated - -StorageClient is deprecated. Use Minio.Client directly. - -## Properties - -### ~~endPoint~~ - -> **endPoint**: `string` - -Defined in: [types.ts:62](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L62) - -Request endPoint - -*** - -### ~~port?~~ - -> `optional` **port**: `number` - -Defined in: [types.ts:74](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L74) - -TCP/IP port number. Default value set to 80 for HTTP and 443 for HTTPs - -*** - -### ~~region?~~ - -> `optional` **region**: `string` - -Defined in: [types.ts:70](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L70) - -Region - -*** - -### ~~useSSL~~ - -> **useSSL**: `boolean` - -Defined in: [types.ts:66](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L66) - -Enable secure (HTTPS) access. Default value set to false diff --git a/docs/sdk/typescript/types/type-aliases/TransactionLikeWithNonce.md b/docs/sdk/typescript/types/type-aliases/TransactionLikeWithNonce.md deleted file mode 100644 index efa93be4e3..0000000000 --- a/docs/sdk/typescript/types/type-aliases/TransactionLikeWithNonce.md +++ /dev/null @@ -1,17 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [types](../README.md) / TransactionLikeWithNonce - -# Type Alias: TransactionLikeWithNonce - -> **TransactionLikeWithNonce** = `TransactionLike` & `object` - -Defined in: [types.ts:146](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L146) - -## Type Declaration - -### nonce - -> **nonce**: `number` diff --git a/docs/sdk/typescript/types/type-aliases/UploadFile.md b/docs/sdk/typescript/types/type-aliases/UploadFile.md deleted file mode 100644 index 22e3859877..0000000000 --- a/docs/sdk/typescript/types/type-aliases/UploadFile.md +++ /dev/null @@ -1,43 +0,0 @@ -[**@human-protocol/sdk**](../../README.md) - -*** - -[@human-protocol/sdk](../../modules.md) / [types](../README.md) / UploadFile - -# Type Alias: UploadFile - -> `readonly` **UploadFile** = `object` - -Defined in: [types.ts:81](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L81) - -Upload file data - -## Properties - -### hash - -> **hash**: `string` - -Defined in: [types.ts:93](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L93) - -Hash of uploaded object key - -*** - -### key - -> **key**: `string` - -Defined in: [types.ts:85](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L85) - -Uploaded object key - -*** - -### url - -> **url**: `string` - -Defined in: [types.ts:89](https://github.com/humanprotocol/human-protocol/blob/0661934b14ae802af3f939783433c196862268e2/packages/sdk/typescript/human-protocol-sdk/src/types.ts#L89) - -Uploaded object URL diff --git a/packages/sdk/python/human-protocol-sdk/Makefile b/packages/sdk/python/human-protocol-sdk/Makefile index de798571ca..89c7f9141d 100644 --- a/packages/sdk/python/human-protocol-sdk/Makefile +++ b/packages/sdk/python/human-protocol-sdk/Makefile @@ -29,12 +29,3 @@ publish-package: run-example: pipenv run python3 example.py - -generate-autodoc: - pipenv run sphinx-apidoc -l -e -M -o ./docs ./human_protocol_sdk */gql && rm -rf ./docs/modules.rst - -clean-doc-md: - rm -rf docs/_build && rm -rf ../../../../docs/sdk/python/* - -generate-doc-md: - make clean-doc-md && cd docs && make markdown && cp -r _build/markdown/* ../../../../../docs/sdk/python diff --git a/packages/sdk/python/human-protocol-sdk/docs/Makefile b/packages/sdk/python/human-protocol-sdk/docs/Makefile deleted file mode 100644 index a2d36df643..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= pipenv run sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/packages/sdk/python/human-protocol-sdk/docs/conf.py b/packages/sdk/python/human-protocol-sdk/docs/conf.py deleted file mode 100644 index 78bde18085..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/conf.py +++ /dev/null @@ -1,54 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -import os -import sys - -sys.path.insert(0, os.path.abspath("..")) - - -def skip(app, what, name, obj, would_skip, options): - if name in ("__init__",): - return False - return would_skip - - -def setup(app): - app.connect("autodoc-skip-member", skip) - - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information - -project = "human_protocol_sdk" -copyright = "2025, HUMAN Protocol" -author = "HUMAN Protocol" - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.viewcode", - "sphinx.ext.todo", - "sphinx_markdown_builder", - "sphinx_autodoc_typehints", -] - -templates_path = ["_templates"] -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] - -language = "en" - -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -html_theme = "alabaster" -html_static_path = ["_static"] - -# -- Options for todo extension ---------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/extensions/todo.html#configuration - -todo_include_todos = True diff --git a/packages/sdk/python/human-protocol-sdk/docs/core.md b/packages/sdk/python/human-protocol-sdk/docs/core.md new file mode 100644 index 0000000000..4322e215dc --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/core.md @@ -0,0 +1,19 @@ +# Core utilities + +Shared constants, filters, decorators, and helpers used across the SDK. + +## Constants + +::: human_protocol_sdk.constants + +## Filters + +::: human_protocol_sdk.filter + +## Decorators + +::: human_protocol_sdk.decorators + +## General utilities + +::: human_protocol_sdk.utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/encryption.md b/packages/sdk/python/human-protocol-sdk/docs/encryption.md new file mode 100644 index 0000000000..a74ff0a99a --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/encryption.md @@ -0,0 +1 @@ +::: human_protocol_sdk.encryption.encryption \ No newline at end of file diff --git a/packages/sdk/python/human-protocol-sdk/docs/encryption_utils.md b/packages/sdk/python/human-protocol-sdk/docs/encryption_utils.md new file mode 100644 index 0000000000..1bd4261de8 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/encryption_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.encryption.encryption_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/escrow_client.md b/packages/sdk/python/human-protocol-sdk/docs/escrow_client.md new file mode 100644 index 0000000000..7a82318136 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/escrow_client.md @@ -0,0 +1 @@ +::: human_protocol_sdk.escrow.escrow_client \ No newline at end of file diff --git a/packages/sdk/python/human-protocol-sdk/docs/escrow_utils.md b/packages/sdk/python/human-protocol-sdk/docs/escrow_utils.md new file mode 100644 index 0000000000..74beb57b57 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/escrow_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.escrow.escrow_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.bootstrap.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.bootstrap.rst deleted file mode 100644 index 753d4f78da..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.bootstrap.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.agreement.bootstrap module -=============================================== - -.. automodule:: human_protocol_sdk.agreement.bootstrap - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.measures.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.measures.rst deleted file mode 100644 index a7a77dca16..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.measures.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.agreement.measures module -============================================== - -.. automodule:: human_protocol_sdk.agreement.measures - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.rst deleted file mode 100644 index 02077ef7e7..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.rst +++ /dev/null @@ -1,17 +0,0 @@ -human\_protocol\_sdk.agreement package -====================================== - -.. automodule:: human_protocol_sdk.agreement - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.agreement.bootstrap - human_protocol_sdk.agreement.measures - human_protocol_sdk.agreement.utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.utils.rst deleted file mode 100644 index 0ae1792d36..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.agreement.utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.agreement.utils module -=========================================== - -.. automodule:: human_protocol_sdk.agreement.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.constants.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.constants.rst deleted file mode 100644 index 2d1ec1a28f..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.constants.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.constants module -===================================== - -.. automodule:: human_protocol_sdk.constants - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.decorators.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.decorators.rst deleted file mode 100644 index 40a6fe5c3b..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.decorators.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.decorators module -====================================== - -.. automodule:: human_protocol_sdk.decorators - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption.rst deleted file mode 100644 index 0f65c3a743..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.encryption.encryption module -================================================= - -.. automodule:: human_protocol_sdk.encryption.encryption - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption_utils.rst deleted file mode 100644 index 8950eda862..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.encryption_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.encryption.encryption\_utils module -======================================================== - -.. automodule:: human_protocol_sdk.encryption.encryption_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.rst deleted file mode 100644 index 7feea3a095..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.encryption.rst +++ /dev/null @@ -1,16 +0,0 @@ -human\_protocol\_sdk.encryption package -======================================= - -.. automodule:: human_protocol_sdk.encryption - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.encryption.encryption - human_protocol_sdk.encryption.encryption_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_client.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_client.rst deleted file mode 100644 index 5315de4f81..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_client.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.escrow.escrow\_client module -================================================= - -.. automodule:: human_protocol_sdk.escrow.escrow_client - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_utils.rst deleted file mode 100644 index 283e6847b8..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.escrow_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.escrow.escrow\_utils module -================================================ - -.. automodule:: human_protocol_sdk.escrow.escrow_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.rst deleted file mode 100644 index 5e91589ec0..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.escrow.rst +++ /dev/null @@ -1,16 +0,0 @@ -human\_protocol\_sdk.escrow package -=================================== - -.. automodule:: human_protocol_sdk.escrow - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.escrow.escrow_client - human_protocol_sdk.escrow.escrow_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.filter.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.filter.rst deleted file mode 100644 index c5d77fc6a6..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.filter.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.filter module -================================== - -.. automodule:: human_protocol_sdk.filter - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_client.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_client.rst deleted file mode 100644 index fbca059a94..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_client.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.kvstore.kvstore\_client module -=================================================== - -.. automodule:: human_protocol_sdk.kvstore.kvstore_client - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_utils.rst deleted file mode 100644 index f03e99b689..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.kvstore_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.kvstore.kvstore\_utils module -================================================== - -.. automodule:: human_protocol_sdk.kvstore.kvstore_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst deleted file mode 100644 index 19b2b74847..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.kvstore.rst +++ /dev/null @@ -1,16 +0,0 @@ -human\_protocol\_sdk.kvstore package -==================================== - -.. automodule:: human_protocol_sdk.kvstore - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.kvstore.kvstore_client - human_protocol_sdk.kvstore.kvstore_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.legacy_encryption.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.legacy_encryption.rst deleted file mode 100644 index b769d604f8..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.legacy_encryption.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.legacy\_encryption module -============================================== - -.. automodule:: human_protocol_sdk.legacy_encryption - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.operator_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.operator_utils.rst deleted file mode 100644 index 1bdfe2a4d1..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.operator_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.operator.operator\_utils module -==================================================== - -.. automodule:: human_protocol_sdk.operator.operator_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.rst deleted file mode 100644 index 87470ef171..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.operator.rst +++ /dev/null @@ -1,15 +0,0 @@ -human\_protocol\_sdk.operator package -===================================== - -.. automodule:: human_protocol_sdk.operator - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.operator.operator_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.rst deleted file mode 100644 index 6e7277a299..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.rst +++ /dev/null @@ -1,35 +0,0 @@ -human\_protocol\_sdk package -============================ - -.. automodule:: human_protocol_sdk - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.agreement - human_protocol_sdk.encryption - human_protocol_sdk.escrow - human_protocol_sdk.kvstore - human_protocol_sdk.operator - human_protocol_sdk.staking - human_protocol_sdk.statistics - human_protocol_sdk.storage - human_protocol_sdk.transaction - human_protocol_sdk.worker - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.constants - human_protocol_sdk.filter - human_protocol_sdk.legacy_encryption - human_protocol_sdk.utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.rst deleted file mode 100644 index b23caacd20..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.rst +++ /dev/null @@ -1,16 +0,0 @@ -human\_protocol\_sdk.staking package -==================================== - -.. automodule:: human_protocol_sdk.staking - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.staking.staking_client - human_protocol_sdk.staking.staking_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_client.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_client.rst deleted file mode 100644 index a28b650821..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_client.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.staking.staking\_client module -=================================================== - -.. automodule:: human_protocol_sdk.staking.staking_client - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_utils.rst deleted file mode 100644 index 65cbdc1fd0..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.staking.staking_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.staking.staking\_utils module -================================================== - -.. automodule:: human_protocol_sdk.staking.staking_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.rst deleted file mode 100644 index c0016e8625..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.rst +++ /dev/null @@ -1,15 +0,0 @@ -human\_protocol\_sdk.statistics package -======================================= - -.. automodule:: human_protocol_sdk.statistics - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.statistics.statistics_client diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.statistics_client.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.statistics_client.rst deleted file mode 100644 index f8dea7552b..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.statistics.statistics_client.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.statistics.statistics\_client module -========================================================= - -.. automodule:: human_protocol_sdk.statistics.statistics_client - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.rst deleted file mode 100644 index 032db98655..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.rst +++ /dev/null @@ -1,16 +0,0 @@ -human\_protocol\_sdk.storage package -==================================== - -.. automodule:: human_protocol_sdk.storage - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.storage.storage_client - human_protocol_sdk.storage.storage_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_client.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_client.rst deleted file mode 100644 index 120e1d662d..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_client.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.storage.storage\_client module -=================================================== - -.. automodule:: human_protocol_sdk.storage.storage_client - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_utils.rst deleted file mode 100644 index 67d384fca5..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.storage.storage_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.storage.storage\_utils module -================================================== - -.. automodule:: human_protocol_sdk.storage.storage_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.rst deleted file mode 100644 index cffcd0c213..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.rst +++ /dev/null @@ -1,15 +0,0 @@ -human\_protocol\_sdk.transaction package -======================================== - -.. automodule:: human_protocol_sdk.transaction - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.transaction.transaction_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.transaction_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.transaction_utils.rst deleted file mode 100644 index 9c71eeff3f..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.transaction.transaction_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.transaction.transaction\_utils module -========================================================== - -.. automodule:: human_protocol_sdk.transaction.transaction_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.utils.rst deleted file mode 100644 index 0c28f44b0c..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.utils module -================================= - -.. automodule:: human_protocol_sdk.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.rst deleted file mode 100644 index 64b0149c33..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.rst +++ /dev/null @@ -1,15 +0,0 @@ -human\_protocol\_sdk.worker package -=================================== - -.. automodule:: human_protocol_sdk.worker - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - human_protocol_sdk.worker.worker_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.worker_utils.rst b/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.worker_utils.rst deleted file mode 100644 index c45ab7bdcc..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/human_protocol_sdk.worker.worker_utils.rst +++ /dev/null @@ -1,7 +0,0 @@ -human\_protocol\_sdk.worker.worker\_utils module -================================================ - -.. automodule:: human_protocol_sdk.worker.worker_utils - :members: - :undoc-members: - :show-inheritance: diff --git a/packages/sdk/python/human-protocol-sdk/docs/index.md b/packages/sdk/python/human-protocol-sdk/docs/index.md new file mode 100644 index 0000000000..54585e09c3 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/index.md @@ -0,0 +1,215 @@ +# HUMAN Protocol Python SDK + +The **HUMAN Protocol Python SDK** provides a comprehensive, Pythonic interface for interacting with HUMAN Protocol smart contracts and off-chain services. It enables developers to build decentralized job marketplaces, data labeling platforms, and other human-in-the-loop applications on blockchain networks. + +## Overview + +HUMAN Protocol is a decentralized infrastructure for coordinating human work at scale. The Python SDK simplifies integration by providing high-level abstractions for: + +- **Escrow Management**: Create, fund, and manage escrow contracts for job distribution +- **Staking Operations**: Stake HMT tokens and manage operator allocations +- **On-chain Storage**: Store and retrieve configuration data using KVStore +- **Operator Discovery**: Query and filter operators by role, reputation, and capabilities +- **Worker Analytics**: Track worker performance and payout history +- **Statistics**: Access protocol-wide metrics and analytics +- **Encryption**: Secure message encryption using PGP for private communications + +!!! info "Subgraph access and rate limits" + The SDK calls public subgraph endpoints by default. Unauthenticated requests are rate-limited and may return errors. For higher limits, use your own [API key](https://thegraph.com/docs/it/subgraphs/querying/managing-api-keys/). + +## Key Features + +### Smart Contract Interactions + +- **Escrow Client**: Full lifecycle management of escrow contracts + - Create, fund, and configure escrows + - Bulk payout distribution + - Store and verify results with hash validation + - Cancel and refund mechanisms +- **Staking Client**: Manage HMT token staking + - Stake, unstake, and withdraw operations + - Slash malicious operators + - Query staking information +- **KVStore Client**: On-chain key-value storage + - Store operator configuration + - Manage URLs with automatic hash verification + - Retrieve public keys and metadata + +### Subgraph Utilities + +- **EscrowUtils**: Query escrow data, status events, and payouts +- **OperatorUtils**: Discover operators by role, reputation network, and rewards +- **WorkerUtils**: Access worker statistics and payout history +- **StatisticsUtils**: Retrieve protocol statistics and HMT token metrics +- **TransactionUtils**: Query on-chain transactions with advanced filters + +### Developer Tools + +- **Encryption**: PGP-based message encryption and signing +- **Filters**: Flexible query builders for subgraph data +- **Type Safety**: Comprehensive type hints for better IDE support +- **Error Handling**: Descriptive exceptions with clear error messages + +## Installation + +Install the SDK using pip: + +```bash +pip install human-protocol-sdk +``` + +For development installations with additional dependencies: + +```bash +pip install human-protocol-sdk[dev] +``` + +## Quick Start + +### Read-Only Operations + +Query escrow data without a signer: + +```python +from web3 import Web3 +from human_protocol_sdk.constants import ChainId +from human_protocol_sdk.escrow import EscrowUtils, EscrowFilter + +# Get escrows from the subgraph +escrows = EscrowUtils.get_escrows( + EscrowFilter( + chain_id=ChainId.POLYGON_AMOY, + status=Status.Pending, + ) +) + +for escrow in escrows: + print(f"Escrow: {escrow.address}") + print(f"Balance: {escrow.balance}") + print(f"Status: {escrow.status}") +``` + +### Write Operations + +Create and fund an escrow with a signer: + +```python +from web3 import Web3 +from web3.middleware import SignAndSendRawMiddlewareBuilder +from human_protocol_sdk.escrow import EscrowClient, EscrowConfig + +# Initialize Web3 with signer +w3 = Web3(Web3.HTTPProvider("https://polygon-amoy-rpc.com")) +private_key = "YOUR_PRIVATE_KEY" +account = w3.eth.account.from_key(private_key) +w3.eth.default_account = account.address +w3.middleware_onion.inject( + SignAndSendRawMiddlewareBuilder.build(private_key), + "SignAndSendRawMiddlewareBuilder", + layer=0, +) + +# Create escrow client +escrow_client = EscrowClient(w3) + +# Create escrow configuration +config = EscrowConfig( + recording_oracle_address="0x...", + reputation_oracle_address="0x...", + exchange_oracle_address="0x...", + recording_oracle_fee=10, + reputation_oracle_fee=10, + exchange_oracle_fee=10, + manifest="https://example.com/manifest.json", + hash="manifest_hash", +) + +# Create and setup escrow +escrow_address = escrow_client.create_fund_and_setup_escrow( + token_address="0x...", + amount=Web3.to_wei(100, "ether"), + job_requester_id="job-123", + escrow_config=config, +) + +print(f"Created escrow: {escrow_address}") +``` + +### Query Statistics + +Access protocol-wide statistics: + +```python +from human_protocol_sdk.constants import ChainId +from human_protocol_sdk.statistics import StatisticsUtils + +# Get escrow statistics +stats = StatisticsUtils.get_escrow_statistics(ChainId.POLYGON_AMOY) +print(f"Total escrows: {stats.total_escrows}") + +# Get HMT token statistics +hmt_stats = StatisticsUtils.get_hmt_statistics(ChainId.POLYGON_AMOY) +print(f"Total holders: {hmt_stats.total_holders}") +print(f"Total transfers: {hmt_stats.total_transfer_count}") +``` + +### Operator Discovery + +Find operators by role and reputation: + +```python +from human_protocol_sdk.constants import ChainId +from human_protocol_sdk.operator import OperatorUtils, OperatorFilter + +# Find recording oracles +operators = OperatorUtils.get_operators( + OperatorFilter( + chain_id=ChainId.POLYGON_AMOY, + roles=["Recording Oracle"], + ) +) + +for operator in operators: + print(f"Operator: {operator.address}") + print(f"Role: {operator.role}") + print(f"Staked: {operator.staked_amount}") +``` + +## Supported Networks + +The SDK supports multiple blockchain networks: + +- **Mainnet**: Ethereum, Polygon, BSC +- **Testnets**: Sepolia, Polygon Amoy, BSC Testnet +- **Local Development**: Localhost (Hardhat/Ganache) + +Network configurations are automatically loaded based on the Web3 chain ID. + +## Architecture + +The SDK is organized into several modules: + +- **`escrow`**: Escrow contract client and utilities +- **`staking`**: Staking contract client and utilities +- **`kvstore`**: Key-value store client and utilities +- **`operator`**: Operator discovery and management utilities +- **`worker`**: Worker statistics utilities +- **`statistics`**: Protocol statistics utilities +- **`transaction`**: Transaction query utilities +- **`encryption`**: PGP encryption helpers +- **`constants`**: Network configurations and enums +- **`filter`**: Query filter builders + +## Requirements + +- Python 3.8 or higher +- Web3.py 6.0+ +- Access to an Ethereum-compatible RPC endpoint +- (Optional) Private key for transaction signing + +## Resources + +- [GitHub Repository](https://github.com/humanprotocol/human-protocol) +- [HUMAN Protocol Documentation](https://docs.humanprotocol.org/) +- [Discord Community](https://discord.gg/humanprotocol) +- [Website](https://www.humanprotocol.org/) diff --git a/packages/sdk/python/human-protocol-sdk/docs/index.rst b/packages/sdk/python/human-protocol-sdk/docs/index.rst deleted file mode 100644 index 69f27a5333..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/index.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. Human Protocol SDK documentation master file, created by - sphinx-quickstart on Mon Nov 6 07:49:01 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Human Protocol SDK's documentation! -============================================== - -Installation ------------- - -To install the Human Protocol SDK, run the following command: - -.. code-block:: bash - - pip install human-protocol-sdk - -In case you want to use the features of the agreement module, make sure to install corresponding extras as well. - -.. code-block:: bash - - pip install human-protocol-sdk[agreement] - -.. toctree:: - :maxdepth: 4 - :caption: Contents: - - human_protocol_sdk diff --git a/packages/sdk/python/human-protocol-sdk/docs/kvstore_client.md b/packages/sdk/python/human-protocol-sdk/docs/kvstore_client.md new file mode 100644 index 0000000000..a15ceba06a --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/kvstore_client.md @@ -0,0 +1 @@ +::: human_protocol_sdk.kvstore.kvstore_client \ No newline at end of file diff --git a/packages/sdk/python/human-protocol-sdk/docs/kvstore_utils.md b/packages/sdk/python/human-protocol-sdk/docs/kvstore_utils.md new file mode 100644 index 0000000000..2f8dd26e77 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/kvstore_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.kvstore.kvstore_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/legacy_encryption.md b/packages/sdk/python/human-protocol-sdk/docs/legacy_encryption.md new file mode 100644 index 0000000000..029badfba0 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/legacy_encryption.md @@ -0,0 +1 @@ +::: human_protocol_sdk.legacy_encryption \ No newline at end of file diff --git a/packages/sdk/python/human-protocol-sdk/docs/make.bat b/packages/sdk/python/human-protocol-sdk/docs/make.bat deleted file mode 100644 index 32bb24529f..0000000000 --- a/packages/sdk/python/human-protocol-sdk/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/packages/sdk/python/human-protocol-sdk/docs/operator_utils.md b/packages/sdk/python/human-protocol-sdk/docs/operator_utils.md new file mode 100644 index 0000000000..e27818c5c9 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/operator_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.operator.operator_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/staking_client.md b/packages/sdk/python/human-protocol-sdk/docs/staking_client.md new file mode 100644 index 0000000000..8da1761f9d --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/staking_client.md @@ -0,0 +1 @@ +::: human_protocol_sdk.staking.staking_client \ No newline at end of file diff --git a/packages/sdk/python/human-protocol-sdk/docs/staking_utils.md b/packages/sdk/python/human-protocol-sdk/docs/staking_utils.md new file mode 100644 index 0000000000..2fe082b8c7 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/staking_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.staking.staking_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/statistics_utils.md b/packages/sdk/python/human-protocol-sdk/docs/statistics_utils.md new file mode 100644 index 0000000000..bfb3c48dc9 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/statistics_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.statistics.statistics_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/transaction_utils.md b/packages/sdk/python/human-protocol-sdk/docs/transaction_utils.md new file mode 100644 index 0000000000..f2e6b4132e --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/transaction_utils.md @@ -0,0 +1 @@ +::: human_protocol_sdk.transaction.transaction_utils diff --git a/packages/sdk/python/human-protocol-sdk/docs/worker_utils.md b/packages/sdk/python/human-protocol-sdk/docs/worker_utils.md new file mode 100644 index 0000000000..b8c639b1f3 --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/docs/worker_utils.md @@ -0,0 +1,7 @@ +# Worker + +Helpers for retrieving worker information from the protocol. + +## Utilities + +::: human_protocol_sdk.worker.worker_utils diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/__init__.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/__init__.py deleted file mode 100644 index 8b06fbdc66..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -""" -**A subpackage for calculating Inter Rater Agreement measures for annotated data.** - -This module contains methods that estimate the agreement -between annotatorsin a data labelling project. -Its role is to provide easy access to means of estimating data quality -for developers of Reputation and Recording Oracles. - -Getting Started -=============== -This module is an optional extra of the HUMAN Protocol SDK. -In order to use it, run the following command: - -.. code-block:: bash - - pip install human_protocol_sdk[agreement] - -A simple example ----------------- -The main functionality of the module is provided by a single function called [`agreement`](human_protocol_sdk.agreement.measures.md#human_protocol_sdk.agreement.measures.agreement). -Suppose we have a very small annotation, where 3 annotators label 4 different images. -The goal is to find find if an image contain a cat or not, -so they label them either `cat` or `not`. - -After processing, the data might look look like that: - -.. code-block:: python - - from numpy import nan - annotations = [ - ['cat', 'not', 'cat'], - ['cat', 'cat', 'cat'], - ['not', 'not', 'not'], - ['cat', nan, 'not'], - ] - -Each row contains the annotations for a single item and -each column contains the annotations of an individual annotator. -We call this format `'annotation'` format, -which is the default format expected by the `agreement` function -and all measures implemented in this package. - -Our data contains a missing value, indicated by the `nan` entry. -Annotator 2 did not provide an annotation for item 4. -All missing values must be marked in this way. - -So, we can simply plug our annotations into the function. - -.. code-block:: python - - agreement_report = agreement(annotations, measure="fleiss_kappa") - print(agreement_report) - # { - # 'results': { - # 'measure': 'fleiss_kappa', - # 'score': 0.3950000000000001, - # 'ci': None, - # 'confidence_level': None - # }, - # 'config': { - # 'measure': 'fleiss_kappa', - # 'labels': array(['cat', 'not'], dtype=' Tuple[Tuple[float, float], np.ndarray]: - """Returns a tuple, containing the confidence interval for the boostrap estimates of the given statistic and statistics of the bootstrap samples. - - :param data: Data to estimate the statistic. - :param statistic_fn: Function to calculate the statistic. statistic_fn(data) must return a number. - :param n_iterations: Number of bootstrap samples to use for the estimate. - :param n_sample: If provided, determines the size of each bootstrap sample - drawn from the data. If omitted, is equal to the length of the data. - :param confidence_level: Size of the confidence interval. - :param algorithm: Which algorithm to use for the confidence interval - estimation. "bca" uses the "Bias Corrected Bootstrap with - Acceleration", "percentile" simply takes the appropriate - percentiles from the bootstrap distribution. - :param seed: Random seed to use. - - :return: Confidence interval and bootstrap distribution. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.bootstrap import confidence_interval - import numpy as np - - np.random.seed(42) - data = np.random.randn(10_000) - fn = np.mean - sample_mean = fn(data) - print(f"Sample mean is {sample_mean:.3f}") - # Sample mean is -0.002 - - cl = 0.99 - ci, _ = confidence_interval(data, fn, confidence_level=cl) - print(f"Population mean is between {ci[0]:.2f} and {ci[1]:.2f} with a probablity of {cl}") - # Population mean is between -0.02 and 0.02 with a probablity of 0.99 - - """ - # set random seed for reproducibility - if seed is not None: - np.random.seed(seed) - random.seed(seed) - - data = np.asarray(data) - - if n_iterations < 1: - raise ValueError( - f"n_iterations must be a positive integer, but were {n_iterations}" - ) - - n_data = len(data) - if n_data < 30: - warn( - "Dataset size is low, bootstrap estimate might be inaccurate. For accurate results, make sure to provide at least 30 data points." - ) - - if n_sample is None: - n_sample = n_data - elif n_sample < 1: - raise ValueError(f"n_sample must be a positive integer, but was {n_sample}") - - if not (0.0 <= confidence_level <= 1.0): - raise ValueError( - f"ci must be a float within [0.0, 1.0], but was {confidence_level}" - ) - - # bootstrap estimates - theta_b = np.empty(n_iterations, dtype=float) - for i in range(n_iterations): - idx = np.random.randint(n_data - 1, size=(n_sample,)) - sample = data[idx] - theta_b[i] = statistic_fn(sample) - theta_b = theta_b[~np.isnan(theta_b)] - - match algorithm: - case "percentile": - alpha = 1.0 - confidence_level - alpha /= 2.0 - q = np.asarray([alpha, 1.0 - alpha]) - case "bca": - # acceleration: estimate a from jackknife bootstrap - theta_hat = statistic_fn(data) - jn_idxs = ~np.eye(n_data, dtype=bool) - theta_jn = np.empty(n_data, dtype=float) - for i in range(n_data): - theta_jn[i] = (n_data - 1) * ( - theta_hat - statistic_fn(data[jn_idxs[i]]) - ) - theta_jn = theta_jn[~np.isnan(theta_jn)] - - a = (np.sum(theta_jn**3) / np.sum(theta_jn**2, axis=-1) ** 1.5) / 6 - - alpha = 1.0 - confidence_level - alpha /= 2 - q = np.asarray([alpha, 1.0 - alpha]) - - # bias correction - N = NormalDistribution() - ppf = np.vectorize(N.ppf) - cdf = np.vectorize(N.cdf) - - # bias term. discrepancy between bootrap values and estimated value - z_0 = ppf(np.mean(theta_b < theta_hat)) - z_u = ppf(q) - z_diff = z_0 + z_u - - q = cdf(z_0 + (z_diff / (1 - a * z_diff))) - case _: - raise ValueError(f"Algorithm '{algorithm}' is not available!") - - # sanity checks - if np.any(np.isnan(q)): - warn( - f"q contains NaN values. Input data is probably invalid. Interval will be (nan, nan). data: {data}" - ) - ci_low = ci_high = np.nan - else: - if np.any((q < 0.0) | (q > 1.0)): - warn( - f"q ({q}) out of bounds. Input data is probably invalid. q will be clipped into interval [0.0, 1.0]. data: {data}" - ) - q = np.clip(q, 0.0, 1.0) - ci_low, ci_high = np.percentile(theta_b, q * 100) - - return (ci_low, ci_high), theta_b diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/measures.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/measures.py deleted file mode 100644 index b0ccf3a7a0..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/measures.py +++ /dev/null @@ -1,377 +0,0 @@ -"""Module containing Inter Rater Agreement Measures.""" - -from copy import copy -from functools import partial -from typing import Sequence, Optional, Callable, Union -from warnings import warn - -import numpy as np - -from .bootstrap import confidence_intervals -from .utils import label_counts, confusion_matrix, observed_and_expected_differences - - -def agreement( - annotations: Sequence, - measure="krippendorffs_alpha", - labels: Optional[Sequence] = None, - bootstrap_method: Optional[str] = None, - bootstrap_kwargs: Optional[dict] = None, - measure_kwargs: Optional[dict] = None, -) -> dict: - """ - Calculates agreement across the given data using the given method. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of annotated items and - M is the number of annotators. Missing values must be indicated by nan. - :param measure: Specifies the method to use. - Must be one of 'cohens_kappa', 'percentage', 'fleiss_kappa', - 'sigma' or 'krippendorffs_alpha'. - :param labels: List of labels to use for the annotation. - If set to None, labels are inferred from the data. - If provided, values not in the labels are set to nan. - :param bootstrap_method: Name of the bootstrap method to use - for calculating confidence intervals. - If set to None, no confidence intervals are calculated. - If provided, must be one of 'percentile' or 'bca'. - :param bootstrap_kwargs: Dictionary of keyword arguments to be passed - to the bootstrap function. - :param measure_kwargs: Dictionary of keyword arguments to be - passed to the measure function. - - :return: A dictionary containing the keys "results" and "config". - Results contains the scores, while config contains parameters - that produced the results. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement import agreement - - annotations = [ - ['cat', 'not', 'cat'], - ['cat', 'cat', 'cat'], - ['not', 'not', 'not'], - ['cat', 'nan', 'not'], - ] - - agreement_report = agreement(annotations, measure="fleiss_kappa") - print(agreement_report) - # { - # 'results': { - # 'measure': 'fleiss_kappa', - # 'score': 0.3950000000000001, - # 'ci': None, - # 'confidence_level': None - # }, - # 'config': { - # 'measure': 'fleiss_kappa', - # 'labels': array(['cat', 'not'], dtype=' float: - """ - Returns the overall agreement percentage observed across the data. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of annotated items and - M is the number of annotators. Missing values must be indicated by nan. - - :return: Value between 0.0 and 1.0, indicating the percentage of agreement. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.measures import percentage - import numpy as np - - annotations = np.asarray([ - ["cat", "not", "cat"], - ["cat", "cat", "cat"], - ["not", "not", "not"], - ["cat", "cat", "not"], - ]) - print(percentage(annotations)) - # 0.7 - """ - annotations = np.asarray(annotations) - return _percentage_from_label_counts(label_counts(annotations)) - - -def _percentage_from_label_counts(label_counts): - n_raters = np.sum(label_counts, 1) - item_agreements = (np.sum(label_counts * label_counts, 1) - n_raters).sum() - max_item_agreements = (n_raters * (n_raters - 1)).sum() - - if max_item_agreements == 0: - warn( - """ - All annotations were made by a single annotator, - check your data to ensure this is not an error. - Returning 1.0 - """ - ) - return 1.0 - - return item_agreements / max_item_agreements - - -def _kappa(agreement_observed, agreement_expected): - if agreement_expected == 1.0: - warn( - """ - Annotations contained only a single value, - check your data to ensure this is not an error. - Returning 1.0. - """ - ) - return 1.0 - - return (agreement_observed - agreement_expected) / (1 - agreement_expected) - - -def cohens_kappa(annotations: np.ndarray) -> float: - """ - Returns Cohen's Kappa for the provided annotations. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of annotated items and M - is the number of annotators. Missing values must be indicated by nan. - - :return: Value between -1.0 and 1.0, - indicating the degree of agreement between both raters. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.measures import cohens_kappa - import numpy as np - - annotations = np.asarray([ - ["cat", "cat"], - ["cat", "cat"], - ["not", "cat"], - ["not", "cat"], - ["cat", "not"], - ["not", "not"], - ["not", "not"], - ["not", "not"], - ["not", "not"], - ["not", "not"], - ]) - print(cohens_kappa(annotations)) - # 0.348 - """ - annotations = np.asarray(annotations) - cm = confusion_matrix(annotations) - - agreement_observed = np.diag(cm).sum() / cm.sum() - agreement_expected = np.matmul(cm.sum(0), cm.sum(1)) / cm.sum() ** 2 - - return _kappa(agreement_observed, agreement_expected) - - -def fleiss_kappa(annotations: np.ndarray) -> float: - """ - Returns Fleisss' Kappa for the provided annotations. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of items and - M is the number of annotators. - - :return: Value between -1.0 and 1.0, - indicating the degree of agreement between all raters. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.measures import fleiss_kappa - import numpy as np - - # 3 raters, 2 classes - annotations = np.asarray([ - ["cat", "not", "cat"], - ["cat", "cat", "cat"], - ["not", "not", "not"], - ["cat", "cat", "not"], - ]) - print(f"{fleiss_kappa(annotations):.3f}") - # 0.395 - """ - annotations = np.asarray(annotations) - im = label_counts(annotations) - - agreement_observed = _percentage_from_label_counts(im) - class_probabilities = im.sum(0) / im.sum() - agreement_expected = np.power(class_probabilities, 2).sum() - - return _kappa(agreement_observed, agreement_expected) - - -def krippendorffs_alpha( - annotations: np.ndarray, distance_function: Union[Callable, str] -) -> float: - """ - Calculates Krippendorff's Alpha for the given annotations (item-value pairs), - using the given distance function. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of annotated items and - M is the number of annotators. Missing values must be indicated by nan. - :param distance_function: Function to calculate distance between two values. - Calling `distance_fn(annotations[i, j], annotations[p, q])` must return a number. - Can also be one of 'nominal', 'ordinal', 'interval' or 'ratio' for - default functions pertaining to the level of measurement of the data. - - :return: Value between -1.0 and 1.0, - indicating the degree of agreement. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.measures import krippendorffs_alpha - import numpy as np - - annotations = np.asarray([ - [0, 0, 0], - [0, 1, 1]] - ) - print(krippendorffs_alpha(annotations, distance_function="nominal")) - # 0.375 - - """ - difference_observed, difference_expected = observed_and_expected_differences( - annotations, distance_function - ) - return 1 - difference_observed.mean() / difference_expected.mean() - - -def sigma( - annotations: np.ndarray, distance_function: Union[Callable, str], p=0.05 -) -> float: - """ - Calculates the Sigma Agreement Measure for the given annotations (item-value pairs), - using the given distance function. - For details, see https://dl.acm.org/doi/fullHtml/10.1145/3485447.3512242. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of annotated items and - M is the number of annotators. Missing values must be indicated by nan. - :param distance_function: Function to calculate distance between two values. - Calling `distance_fn(annotations[i, j], annotations[p, q])` must return a number. - Can also be one of 'nominal', 'ordinal', 'interval' or 'ratio' for - default functions pertaining to the level of measurement of the data. - :param p: Probability threshold between 0.0 and 1.0 - determining statistical significant difference. The lower, the stricter. - - :return: Value between 0.0 and 1.0, indicating the degree of agreement. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.measures import sigma - import numpy as np - - np.random.seed(42) - n_items = 500 - n_annotators = 5 - - # create annotations - annotations = np.random.rand(n_items, n_annotators) - means = np.random.rand(n_items, 1) * 100 - scales = np.random.randn(n_items, 1) * 10 - annotations = annotations * scales + means - d = "interval" - - print(sigma(annotations, d)) - # 0.6538 - """ - if p < 0.0 or p > 1.0: - raise ValueError(f"Parameter 'p' must be between 0.0 and 1.0") - - difference_observed, difference_expected = observed_and_expected_differences( - annotations, distance_function - ) - difference_crit = np.quantile(difference_expected, p) - return np.mean(difference_observed < difference_crit) diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/utils.py deleted file mode 100644 index 8267537315..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/agreement/utils.py +++ /dev/null @@ -1,417 +0,0 @@ -"""Module containing helper functions for calculating agreement measures.""" - -from collections import Counter -from math import nan -from typing import Sequence, Optional, Tuple - -import numpy as np -from pyerf import erf, erfinv - - -def _filter_labels(labels: Sequence): - """ - Filters None and nan values from the given labels. - - :param labels: The labels to filter. - - :return: A list of labels without the given list of labels to exclude. - - """ - # map to preserve label order if user defined labels are passed - nan_values = {np.nan, nan, None, "nan"} - return np.asarray([label for label in labels if label not in nan_values]) - - -def _is_nan(data: np.ndarray, axis=None): - """np.isnan but for any data type.""" - try: - mask = np.isnan(data) - except TypeError: - mask = data == "nan" - - if axis is not None: - mask = np.any(mask, axis=axis) - - return mask - - -def _is_in(data: np.ndarray, elements: np.ndarray): - """Checks if data is in elements. Faster than using np.isin.""" - return data[..., np.newaxis] == elements - - -def label_counts( - annotations: Sequence, - labels=None, - return_labels=False, -): - """Converts the given sequence of item annotations to an array of label counts per item. - - :param annotations: A two-dimensional sequence. Rows represent items, columns represent annotators. - :param labels: List of labels to be counted. Entries not found in the list are omitted. If - omitted, all labels in the annotations are counted. - :param nan_values: Values in the records to be counted as invalid. - :param return_labels: Whether to return labels with the counts. Automatically set to true if labels are - inferred. - - :return: A two-dimensional array of integers. Rows represent items, columns represent labels. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.utils import label_counts - - annotations = [ - ["white", "black", "white"], - ["white", "white", "white"], - ["black", "black", "black"], - ["white", "nan", "black"], - ] - - # infer labels automatically - counts, labels = label_counts(annotations, return_labels=True) - print(counts) - # [[1 2] - # [0 3] - # [3 0] - # [1 1]] - - # labels are inferred and sorted automatically - print(labels) - # ['black' 'white'] - - .. code-block:: python - - # labels are provided, label order is preserved - counts, labels = label_counts( - annotations, - labels=['white', 'black'], - return_labels=True - ) - print(counts) - # [[2 1] - # [3 0] - # [0 3] - # [1 1]] - - print(labels) - # ['white' 'black'] - - .. code-block:: python - - # can be achieved using nan values - counts, labels = label_counts( - annotations, - nan_values=[''], - return_labels=True - ) - - print(counts) - # [[1 2] - # [0 3] - # [3 0] - # [1 1]] - - print(labels) - # ['black' 'white'] - - """ - annotations = np.asarray(annotations) - - if labels is None: - labels = np.unique(annotations) - - labels = _filter_labels(labels) - - def lcs(annotations, labels): - c = Counter(annotations) - return [c.get(label, 0) for label in labels] - - counts = np.asarray([lcs(row, labels) for row in annotations]) - - if return_labels: - return counts, labels - - return counts - - -def confusion_matrix( - annotations: np.ndarray, - labels: Optional[Sequence] = None, - return_labels=False, -): - """Generate an N X N confusion matrix from the given sequence of values a and b, - where N is the number of unique labels. - - :param annotations: Annotation data to be converted into confusion matrix. - Must be a N x 2 Matrix, where N is the number of items and 2 is the number of annotators. - :param labels: Sequence of labels to be counted. - Entries not found in the list are omitted. - No labels are provided, the list of labels is inferred from the given annotations. - :param return_labels: Whether to return labels with the counts. - - :return: A confusion matrix. - Rows represent labels assigned by b, columns represent labels assigned by a. - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.utils import confusion_matrix - import numpy as np - - annotations = np.asarray([ - ["a", "a"], - ["b", "a"], - ["c", "c"] - ]) - - # infer labels automatically - cm = confusion_matrix(annotations, return_labels=False) - print(cm) - # [[1 0 0] - # [1 0 0] - # [0 0 1]] - """ - annotations = np.asarray(annotations) - - # create list of unique labels - if labels is None: - labels = np.unique(annotations) - - labels = _filter_labels(labels) - n_labels = len(labels) - - # map labels to ids - label_to_id = {label: i for i, label in enumerate(labels)} - map_fn = np.vectorize(lambda x: label_to_id.get(x, -1)) - M = map_fn(annotations) - - # filter NaN values - mask = np.all(M != -1, axis=1) - - # get indices and counts to populate confusion matrix - cm = np.zeros((n_labels, n_labels), dtype=int) - (i, j), counts = np.unique(M[mask].T, axis=1, return_counts=True) - cm[i, j] = counts - - if return_labels: - return cm, labels - - return cm - - -class NormalDistribution: - """Continuous Normal Distribution. - - See: https://en.wikipedia.org/wiki/Normal_distribution - """ - - def __init__(self, location: float = 0.0, scale: float = 1.0): - """Creates a NormalDistribution from the given parameters. - - :param location: Location of the distribution. - :param scale: Scale of the distribution. Must be positive. - """ - if scale < 0.0: - raise ValueError(f"scale parameter needs to be positive, but was {scale}") - - self.location = location - self.scale = scale - - def cdf(self, x: float) -> float: - """Cumulative Distribution Function of the Normal Distribution. Returns - the probability that a random sample will be less than the given - point. - - :param x: Point within the distribution's domain. - """ - return (1 + erf((x - self.location) / (self.scale * 2**0.5))) / 2 - - def pdf(self, x: float) -> float: - """Probability Density Function of the Normal Distribution. Returns the - probability for observing the given sample in the distribution. - - :param x: Point within the distribution's domain. - """ - return np.exp(-0.5 * (x - self.location / self.scale) ** 2) / ( - self.scale * (2 * np.pi) ** 0.5 - ) - - def ppf(self, p: float) -> float: - """Probability Point function of the Normal Distribution. Returns - the maximum point to which cumulated probabilities equal the given - probability. Also called quantile. Inverse of the cdf. - - :param p: Percentile of the distribution to be covered by the ppf. - """ - if not (0.0 <= p <= 1.0): - raise ValueError(f"p must be a float within [0.0, 1.0], but was {p}") - - return self.location + self.scale * 2**0.5 * erfinv(2 * p - 1.0) - - -def _distance_matrix(values, distance_fn, dtype=np.float64): - """ - Calculates a matrix containing the distances between each pair of given - values using the given distance function. - - :param values: A sequence of values to compute distances between. Assumed to be - unique. - :param distance_fn: Function to calculate distance between two values. Calling - `distance_fn(values[i], values[j])` must return a number. - :param dtype: The datatype of the returned ndarray. - - :return: The distance matrix as a 2d ndarray. - """ - n = len(values) - dist_matrix = np.zeros((n, n), dtype) - i, j = np.triu_indices(n, k=1) - distances = np.vectorize(distance_fn)(values[i], values[j]) - dist_matrix[i, j] = distances - dist_matrix[j, i] = distances - return dist_matrix - - -def _pair_indices(items: np.ndarray): - """ - Returns indices of pairs of identical items. Indices are represented as a numpy ndarray, where the first row contains indices for the first parts of the pairs and the second row contains the second pair index. - - :param items: The items for which to generate pair indices. - - :return: A numpy ndarray, containing indices for pairs of identical items. - """ - items = np.asarray(items) - identical = ( - items[np.newaxis, ...] == items[..., np.newaxis] - ) # elementwise comparison of each item. returns n*n indicator matrix - return np.vstack(np.where(np.triu(identical, 1))) - - -def observed_and_expected_differences(annotations, distance_function): - """ - Returns observed and expected differences for given annotations (item-value - pairs), as used in Krippendorff's alpha agreement measure and the Sigma - agreement measure. - - :param annotations: Annotation data. - Must be a N x M Matrix, where N is the number of items and M is the number of annotators. - :param distance_function: Function to calculate distance between two values. - Calling `distance_fn(annotations[i, j], annotations[p, q])` must return a number. - Can also be one of 'nominal', 'ordinal', 'interval' or 'ratio' for - default functions pertaining to the level of measurement of the data. - - :return: A tuple consisting of numpy ndarrays, - containing the observed and expected differences in annotations. - - """ - values, items, _ = records_from_annotations(annotations) - - if isinstance(distance_function, str): - match distance_function: - case "nominal": - distance_function = lambda a, b: a != b - case "ordinal": - distance_function = lambda a, b: (a - b) ** 2 - case "interval": - distance_function = lambda a, b: (a - b) ** 2 - case "ratio": - distance_function = lambda a, b: ((a - b) / (a + b)) ** 2 - case _: - raise ValueError( - f"Distance function '{distance_function}' not supported." - ) - - unique_values, value_ids = np.unique(values, return_inverse=True) - dist_matrix = _distance_matrix(unique_values, distance_function) - - intra_item_pairs = _pair_indices(items) - i, j = value_ids[intra_item_pairs] - observed_differences = dist_matrix[i, j] - - all_item_pairs = np.vstack(np.triu_indices(n=items.size, k=1)) - i, j = value_ids[all_item_pairs] - expected_differences = dist_matrix[i, j] - - return observed_differences, expected_differences - - -def records_from_annotations( - annotations: np.ndarray, annotators=None, items=None, labels=None -) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: - """ - Turns given annotations into sequences of records. - - :param annotations: Annotation matrix (2d array) to convert. Columns represent - :param annotators: List of annotator ids. Must be the same length as columns in annotations. - :param items: List of item ids. Must be the same length as rows in annotations. - :param labels: The to be included in the matrix. - - :return: Tuple containing arrays of item value ids, item ids and annotator ids - - :example: - .. code-block:: python - - from human_protocol_sdk.agreement.utils import records_from_annotations - import numpy as np - - annotations = np.asarray([ - ["cat", "not", "cat"], - ["cat", "cat", "cat"], - ["not", "not", "not"], - ["cat", np.nan, "not"], - ]) - - # nan values are automatically filtered - values, items, annotators = records_from_annotations(annotations) - print(values) - # ['cat' 'not' 'cat' 'cat' 'cat' 'cat' 'not' 'not' 'not' 'cat' 'not'] - print(items) - # [0 0 0 1 1 1 2 2 2 3 3] - print(annotators) - # [0 1 2 0 1 2 0 1 2 0 2] - - .. code-block:: python - - annotators = np.asarray(["bob", "alice", "charlie"]) - items = np.asarray(["item_1", "item_2", "item_3", "item_4"]) - - values, items, annotators = records_from_annotations( - annotations, - annotators, - items - ) - print(values) - # ['cat' 'not' 'cat' 'cat' 'cat' 'cat' 'not' 'not' 'not' 'cat' 'not'] - print(items) - # ['item_1' 'item_1' 'item_1' 'item_2' 'item_2' 'item_2' 'item_3' 'item_3' 'item_3' 'item_4' 'item_4'] - print(annotators) - # ['bob' 'alice' 'charlie' 'bob' 'alice' 'charlie' 'bob' 'alice' 'charlie' 'bob' 'charlie'] - """ - annotations = np.asarray(annotations) - n_items, n_annotators = annotations.shape - - if items is None: - items = np.arange(n_items) - else: - items = np.asarray(items) - if len(items) != n_items: - raise ValueError( - "Number of items does not correspond to number of rows in annotations." - ) - - if annotators is None: - annotators = np.arange(n_annotators) - else: - annotators = np.asarray(annotators) - if len(annotators) != n_annotators: - raise ValueError( - "Number of annotators does not correspond to number of columns in annotations." - ) - - values = annotations.ravel() - items = np.repeat(items, n_annotators) - annotators = np.tile(annotators, n_items) - - mask = ~_is_nan(values) - - return values[mask], items[mask], annotators[mask] diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py index 4c0abcf005..04960c348b 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/constants.py @@ -4,7 +4,17 @@ class ChainId(Enum): - """Enum for chain IDs.""" + """Supported blockchain network identifiers. + + Attributes: + MAINNET: Ethereum Mainnet (Chain ID: 1) + SEPOLIA: Ethereum Sepolia Testnet (Chain ID: 11155111) + BSC_MAINNET: Binance Smart Chain Mainnet (Chain ID: 56) + BSC_TESTNET: Binance Smart Chain Testnet (Chain ID: 97) + POLYGON: Polygon Mainnet (Chain ID: 137) + POLYGON_AMOY: Polygon Amoy Testnet (Chain ID: 80002) + LOCALHOST: Local development network (Chain ID: 1338) + """ MAINNET = 1 SEPOLIA = 11155111 @@ -16,14 +26,24 @@ class ChainId(Enum): class OrderDirection(Enum): - """Enum for chain IDs.""" + """Sort order for query results. + + Attributes: + ASC: Ascending order (lowest to highest). + DESC: Descending order (highest to lowest). + """ ASC = "asc" DESC = "desc" class OperatorCategory(Enum): - """Enum for operator categories""" + """Categories for operator classification. + + Attributes: + MACHINE_LEARNING: Operators providing machine learning services. + MARKET_MAKING: Operators providing market making services. + """ MACHINE_LEARNING = "machine_learning" MARKET_MAKING = "market_making" @@ -146,10 +166,21 @@ class OperatorCategory(Enum): SUBGRAPH_API_KEY_PLACEHOLDER = "[SUBGRAPH_API_KEY]" +"""Placeholder string in subgraph URLs that gets replaced with the actual API key from environment variables.""" class Status(Enum): - """Enum for escrow statuses.""" + """Escrow contract lifecycle statuses. + + Attributes: + Launched: Escrow created but not yet funded or configured. + Pending: Escrow funded and awaiting oracle actions. + Partial: Escrow partially paid out to workers. + Paid: All funds distributed but not yet marked complete. + Complete: Escrow fully processed and finalized. + Cancelled: Escrow cancelled and funds refunded. + ToCancel: Cancellation requested, awaiting finalization. + """ Launched = 0 Pending = 1 @@ -161,7 +192,14 @@ class Status(Enum): class Role(Enum): - """Enum for roles.""" + """Oracle and operator role identifiers. + + Attributes: + job_launcher: Entity that creates and funds escrows. + exchange_oracle: Oracle handling job distribution and exchange. + reputation_oracle: Oracle managing worker reputation scoring. + recording_oracle: Oracle recording and validating job results. + """ job_launcher = "job_launcher" exchange_oracle = "exchange_oracle" @@ -170,10 +208,28 @@ class Role(Enum): ARTIFACTS_FOLDER = os.path.join(os.path.dirname(os.path.dirname(__file__)), "artifacts") +"""Path to the directory containing compiled smart contract artifacts (ABIs and bytecode).""" class KVStoreKeys(Enum): - """Enum for KVStore keys""" + """Standard key names for the on-chain key-value store. + + These keys are used by operators to store configuration and metadata on-chain. + + Attributes: + category: Operator category classification. + fee: Operator fee percentage. + job_types: Comma-separated list of supported job types. + operator_name: Display name of the operator. + public_key: PGP public key for encrypted communication. + public_key_hash: Hash of the public key file. + registration_instructions: Instructions for worker registration. + registration_needed: Whether registration is required (boolean). + role: Operator role identifier. + url: Primary URL for the operator. + website: Public-facing website URL. + webhook_url: Webhook endpoint for notifications. + """ category = "category" fee = "fee" @@ -190,3 +246,4 @@ class KVStoreKeys(Enum): ESCROW_BULK_PAYOUT_MAX_ITEMS = 99 +"""Maximum number of recipients allowed in a single bulk payout transaction.""" diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/decorators.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/decorators.py index f153b93bd1..0760b95854 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/decorators.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/decorators.py @@ -1,11 +1,55 @@ +"""Decorators for SDK functionality.""" + +from typing import Callable, Any + + class RequiresSignerError(Exception): - """Raised when a signer or required middleware is missing in the Web3 instance.""" + """Raised when a transaction-signing method is called without proper Web3 account configuration. + + This exception is raised by the `@requires_signer` decorator when a method requiring + transaction signing capabilities is invoked on a Web3 instance that lacks: + + - A default account (w3.eth.default_account) + - SignAndSendRawMiddlewareBuilder middleware for transaction signing + """ pass -def requires_signer(method): - def wrapper(self, *args, **kwargs): +def requires_signer(method: Callable[..., Any]) -> Callable[..., Any]: + """Decorator that ensures Web3 instance has signing capabilities before executing a method. + + This decorator validates that the Web3 instance has both a default account configured + and the SignAndSendRawMiddlewareBuilder middleware installed. These are required for + methods that need to sign and send transactions. + + Args: + method (Callable[..., Any]): The method to decorate (must be a method of a class with a `w3` attribute). + + Returns: + Wrapped method that performs validation before execution. + + Raises: + RequiresSignerError: If the Web3 instance lacks a default account or signing middleware. + + Example: + ```python + from web3 import Web3 + from web3.middleware import SignAndSendRawMiddlewareBuilder + from human_protocol_sdk.decorators import requires_signer + + class MyClient: + def __init__(self, w3): + self.w3 = w3 + + @requires_signer + def send_transaction(self): + # This method requires a signer + pass + ``` + """ + + def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any: if not self.w3.eth.default_account: raise RequiresSignerError("You must add an account to Web3 instance") if not self.w3.middleware_onion.get("SignAndSendRawMiddlewareBuilder"): diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption.py index 284b30fbd1..1bf00a16e2 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption.py @@ -1,44 +1,4 @@ -""" -This class allows signing, verifying, encrypting, and -decrypting messages at all levels of escrow processing. - -The algorithm includes the implementation of the -[PGP encryption algorithm](https://github.com/openpgpjs/openpgpjs) -multi-public key encryption in Python. -Using the vanilla [ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) -implementation Schnorr signatures for signature and -[curve25519](https://en.wikipedia.org/wiki/Curve25519) for encryption. -Learn [more](https://wiki.polkadot.network/docs/learn-cryptography). - -Code Example ------------- - -.. code-block:: python - - from human_protocol_sdk.encryption import Encryption - - private_key = \"\"\"-----BEGIN PGP PRIVATE KEY BLOCK----- - - xVgEZJ1mYRYJKwYBBAHaRw8BAQdAGLLi15zjuVhD4eUOYR5v40kDyRb3nrkh - 0tO5pPNXBIkAAQCXERVkGLDJadkZ3yzerGQeJyxM0Xl5IaEWrzQsSCt/mwz7 - zRRIdW1hbiA8aHVtYW5AaG10LmFpPsKMBBAWCgA+BQJknWZhBAsJBwgJEAyX - rIbvfPxlAxUICgQWAAIBAhkBAhsDAh4BFiEEGWQNXhKpp2hxuxetDJeshu98 - /GUAAFldAP4/HVRKEso+QiphYxfAIPbCbrZ+xy6RTFAW0tdjpDQwJQD+P81w - 74pFhmBFjb8Aio87M1lLRzLSXjEVpKEciGerkQjHXQRknWZhEgorBgEEAZdV - AQUBAQdA+/XEHJiIC5GtJPxgybd2TyJe5kzTyh0+uzwAgD33R3cDAQgHAAD/ - brJ3/2P+H4wOTV25YBp+UVvE0MqiVrCLk5kBNJdpN8AQn8J4BBgWCAAqBQJk - nWZhCRAMl6yG73z8ZQIbDBYhBBlkDV4SqadocbsXrQyXrIbvfPxlAAC04QD+ - Jyyd/rDd4bEuAvsHFQHK2HMC2r0OLVHdMjygPELEA+sBANNtHfc60ts3++D7 - dhjPN+xEYS1/BntokSSwC8mi56AJ - =GMlv - -----END PGP PRIVATE KEY BLOCK-----\"\"\" - passphrase = "passphrase" - - encryption = Encryption(private_key, passphrase) - -Module ------- -""" +"""Encrypt, decrypt, sign, and verify messages using PGP.""" from typing import Optional, List, Union from pgpy import PGPKey, PGPMessage @@ -47,16 +7,36 @@ class Encryption: - """ - A class that provides encryption and decryption functionality using PGP (Pretty Good Privacy). + """Encryption and decryption helper using PGP (Pretty Good Privacy). + + This class provides methods to sign, encrypt, decrypt, and verify messages + using PGP encryption with private/public key pairs. + + Attributes: + private_key (PGPKey): The unlocked PGP private key. + passphrase (Optional[str]): Passphrase used to unlock the private key. """ def __init__(self, private_key_armored: str, passphrase: Optional[str] = None): - """ - Initializes an Encryption instance. + """Initialize an Encryption instance with a private key. + + Args: + private_key_armored (str): Armored representation of the PGP private key. + passphrase (Optional[str]): Passphrase to unlock the private key if it's locked. - :param private_key_armored: Armored representation of the private key - :param passphrase: Passphrase to unlock the private key. Defaults to None. + Raises: + ValueError: If the private key is invalid, cannot be unlocked with the passphrase, + or is locked and no passphrase is provided. + + Example: + ```python + from human_protocol_sdk.encryption import Encryption + + encryption = Encryption( + "-----BEGIN PGP PRIVATE KEY BLOCK-----...", + "your-passphrase" + ) + ``` """ try: self.private_key, _ = PGPKey.from_blob(private_key_armored) @@ -77,69 +57,30 @@ def __init__(self, private_key_armored: str, passphrase: Optional[str] = None): def sign_and_encrypt( self, message: Union[str, bytes], public_keys: List[str] ) -> str: - """ - Signs and encrypts a message using the private key and recipient's public keys. - - :param message: Message to sign and encrypt - :param public_keys: List of armored public keys of the recipients - - :return: Armored and signed/encrypted message - - :example: - .. code-block:: python - - from human_protocol_sdk.encryption import Encryption - - private_key = \"\"\"-----BEGIN PGP PRIVATE KEY BLOCK----- - - xVgEZJ1mYRYJKwYBBAHaRw8BAQdAGLLi15zjuVhD4eUOYR5v40kDyRb3nrkh - 0tO5pPNXBIkAAQCXERVkGLDJadkZ3yzerGQeJyxM0Xl5IaEWrzQsSCt/mwz7 - zRRIdW1hbiA8aHVtYW5AaG10LmFpPsKMBBAWCgA+BQJknWZhBAsJBwgJEAyX - rIbvfPxlAxUICgQWAAIBAhkBAhsDAh4BFiEEGWQNXhKpp2hxuxetDJeshu98 - /GUAAFldAP4/HVRKEso+QiphYxfAIPbCbrZ+xy6RTFAW0tdjpDQwJQD+P81w - 74pFhmBFjb8Aio87M1lLRzLSXjEVpKEciGerkQjHXQRknWZhEgorBgEEAZdV - AQUBAQdA+/XEHJiIC5GtJPxgybd2TyJe5kzTyh0+uzwAgD33R3cDAQgHAAD/ - brJ3/2P+H4wOTV25YBp+UVvE0MqiVrCLk5kBNJdpN8AQn8J4BBgWCAAqBQJk - nWZhCRAMl6yG73z8ZQIbDBYhBBlkDV4SqadocbsXrQyXrIbvfPxlAAC04QD+ - Jyyd/rDd4bEuAvsHFQHK2HMC2r0OLVHdMjygPELEA+sBANNtHfc60ts3++D7 - dhjPN+xEYS1/BntokSSwC8mi56AJ - =GMlv - -----END PGP PRIVATE KEY BLOCK-----\"\"\" - - passphrase = "passphrase" - - public_key2 = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZKKJZRYJKwYBBAHaRw8BAQdAiy9Cvf7Stb5uGaPWTxhk2kEWgwHI75PK - JAN1Re+mZ/7NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSiiWUE - CwkHCAkQLJTUgF16PUcDFQgKBBYAAgECGQECGwMCHgEWIQRHZsSFAPBxClHV - TEYslNSAXXo9RwAAUYYA+gJKoCHiEl/1AUNKZrWBmvS3J9BRAFgvGHFmUKSQ - qvCJAP9+M55C/K0QjO1B9N14TPsnENaB0IIlvavhNUgKow9sBc44BGSiiWUS - CisGAQQBl1UBBQEBB0DWVuH+76KUCwGbLNnrTAGxysoo6TWpkG1upYQvZztB - cgMBCAfCeAQYFggAKgUCZKKJZQkQLJTUgF16PUcCGwwWIQRHZsSFAPBxClHV - TEYslNSAXXo9RwAA0dMBAJ0cd1OM/yWJdaVQcPp4iQOFh7hAOZlcOPF2NTRr - 1AvDAQC4Xx6swMIiu2Nx/2JYXr3QdUO/tBtC/QvU8LPQETo9Cg== - =4PJh - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - public_key3 = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZKLMDhYJKwYBBAHaRw8BAQdAufXwhFItFe4j2IuTa3Yc4lZMNAxV/B+k - X8mJ5PzqY4fNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSizA4E - CwkHCAkQsGTIZV9ne20DFQgKBBYAAgECGQECGwMCHgEWIQTviv8XOCeYpubG - OoWwZMhlX2d7bQAAYAUA/35sTPhzQjm7uPpSTw2ahUfRijlxfKRWc5p36x0L - NX+mAQCxwUgrbR2ngZOa5E+AQM8tyq8fh1qMvrM5hNeNRNf/Cc44BGSizA4S - CisGAQQBl1UBBQEBB0D8B9TjjY+KyoYR9wUE1tCaCi1N4ZoGFKscey3H5y80 - AAMBCAfCeAQYFggAKgUCZKLMDgkQsGTIZV9ne20CGwwWIQTviv8XOCeYpubG - OoWwZMhlX2d7bQAARg0BAMuQnhXzyIbbARtV3dobO7nw+VwCHVs9E7OtzLUi - 25TEAP4m0jWfjq8w+0dM9U+/+r1FqMk/q7RU8Ib8HJXUOMaGBw== - =62qY - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - encryption = Encryption(private_key, passphrase) - encrypted_message = encryption.sign_and_encrypt( - "your message", [public_key2, public_key3] - ) + """Sign and encrypt a message with recipient public keys. + + Signs the message with the private key and encrypts it for all specified recipients. + + Args: + message (Union[str, bytes]): Message content to sign and encrypt. + public_keys (List[str]): List of armored PGP public keys of the recipients. + + Returns: + Armored, signed, and encrypted PGP message. + + Raises: + ValueError: If the private key cannot be unlocked or encryption fails. + + Example: + ```python + from human_protocol_sdk.encryption import Encryption + + encryption = Encryption("-----BEGIN PGP PRIVATE KEY BLOCK-----...", "passphrase") + encrypted_message = encryption.sign_and_encrypt( + "your message", + ["-----BEGIN PGP PUBLIC KEY BLOCK-----..."], + ) + ``` """ pgp_message = PGPMessage.new(message) @@ -164,39 +105,35 @@ def sign_and_encrypt( return pgp_message.__str__() def decrypt(self, message: str, public_key: Optional[str] = None) -> bytes: - """ - Decrypts a message using the private key. - - :param message: Armored message to decrypt - :param public_key: Armored public key used for signature verification. Defaults to None. + """Decrypt a message using the private key. - :return: Decrypted message + Decrypts an encrypted message and optionally verifies the signature using + the sender's public key. - :example: - .. code-block:: python + Args: + message (str): Armored PGP message to decrypt. + public_key (Optional[str]): Optional armored public key to verify the message signature. - from human_protocol_sdk.encryption import Encryption + Returns: + Decrypted message as bytes. - private_key = \"\"\"-----BEGIN PGP PRIVATE KEY BLOCK----- + Raises: + ValueError: If the private key cannot be unlocked, decryption fails, + or signature verification fails when a public key is provided. - xVgEZJ1mYRYJKwYBBAHaRw8BAQdAGLLi15zjuVhD4eUOYR5v40kDyRb3nrkh - 0tO5pPNXBIkAAQCXERVkGLDJadkZ3yzerGQeJyxM0Xl5IaEWrzQsSCt/mwz7 - zRRIdW1hbiA8aHVtYW5AaG10LmFpPsKMBBAWCgA+BQJknWZhBAsJBwgJEAyX - rIbvfPxlAxUICgQWAAIBAhkBAhsDAh4BFiEEGWQNXhKpp2hxuxetDJeshu98 - /GUAAFldAP4/HVRKEso+QiphYxfAIPbCbrZ+xy6RTFAW0tdjpDQwJQD+P81w - 74pFhmBFjb8Aio87M1lLRzLSXjEVpKEciGerkQjHXQRknWZhEgorBgEEAZdV - AQUBAQdA+/XEHJiIC5GtJPxgybd2TyJe5kzTyh0+uzwAgD33R3cDAQgHAAD/ - brJ3/2P+H4wOTV25YBp+UVvE0MqiVrCLk5kBNJdpN8AQn8J4BBgWCAAqBQJk - nWZhCRAMl6yG73z8ZQIbDBYhBBlkDV4SqadocbsXrQyXrIbvfPxlAAC04QD+ - Jyyd/rDd4bEuAvsHFQHK2HMC2r0OLVHdMjygPELEA+sBANNtHfc60ts3++D7 - dhjPN+xEYS1/BntokSSwC8mi56AJ - =GMlv - -----END PGP PRIVATE KEY BLOCK-----\"\"\" + Example: + ```python + from human_protocol_sdk.encryption import Encryption - passphrase = "passphrase" + encryption = Encryption("-----BEGIN PGP PRIVATE KEY BLOCK-----...", "passphrase") + decrypted_message = encryption.decrypt(encrypted_message) - encryption = Encryption(private_key, passphrase) - decrypted_message = encryption.decrypt(encrypted_message) + # Or with signature verification: + decrypted_message = encryption.decrypt( + encrypted_message, + public_key="-----BEGIN PGP PUBLIC KEY BLOCK-----..." + ) + ``` """ pgp_message = PGPMessage.from_blob(message) decrypted_message = "" @@ -229,38 +166,27 @@ def decrypt(self, message: str, public_key: Optional[str] = None) -> bytes: raise ValueError("Failed to decrypt message: {}".format(str(e))) def sign(self, message: Union[str, bytes]) -> str: - """ - Signs a message using the private key. - - :param message: Message to sign - - :return: Armored and signed message + """Sign a message with the private key. - :example: - .. code-block:: python + Creates a cleartext signed message that can be verified by anyone with + the corresponding public key. - from human_protocol_sdk.encryption import Encryption + Args: + message (Union[str, bytes]): Message content to sign. - private_key = \"\"\"-----BEGIN PGP PRIVATE KEY BLOCK----- + Returns: + Armored signed PGP message in cleartext format. - xVgEZJ1mYRYJKwYBBAHaRw8BAQdAGLLi15zjuVhD4eUOYR5v40kDyRb3nrkh - 0tO5pPNXBIkAAQCXERVkGLDJadkZ3yzerGQeJyxM0Xl5IaEWrzQsSCt/mwz7 - zRRIdW1hbiA8aHVtYW5AaG10LmFpPsKMBBAWCgA+BQJknWZhBAsJBwgJEAyX - rIbvfPxlAxUICgQWAAIBAhkBAhsDAh4BFiEEGWQNXhKpp2hxuxetDJeshu98 - /GUAAFldAP4/HVRKEso+QiphYxfAIPbCbrZ+xy6RTFAW0tdjpDQwJQD+P81w - 74pFhmBFjb8Aio87M1lLRzLSXjEVpKEciGerkQjHXQRknWZhEgorBgEEAZdV - AQUBAQdA+/XEHJiIC5GtJPxgybd2TyJe5kzTyh0+uzwAgD33R3cDAQgHAAD/ - brJ3/2P+H4wOTV25YBp+UVvE0MqiVrCLk5kBNJdpN8AQn8J4BBgWCAAqBQJk - nWZhCRAMl6yG73z8ZQIbDBYhBBlkDV4SqadocbsXrQyXrIbvfPxlAAC04QD+ - Jyyd/rDd4bEuAvsHFQHK2HMC2r0OLVHdMjygPELEA+sBANNtHfc60ts3++D7 - dhjPN+xEYS1/BntokSSwC8mi56AJ - =GMlv - -----END PGP PRIVATE KEY BLOCK-----\"\"\" + Raises: + ValueError: If the private key cannot be unlocked or signing fails. - passphrase = "passphrase" + Example: + ```python + from human_protocol_sdk.encryption import Encryption - encryption = Encryption(private_key, passphrase) - signed_message = await encryption.sign("MESSAGE") + encryption = Encryption("-----BEGIN PGP PRIVATE KEY BLOCK-----...", "passphrase") + signed_message = encryption.sign("MESSAGE") + ``` """ message = PGPMessage.new(message, cleartext=True) if not self.private_key.is_unlocked: diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption_utils.py index 98b853d64c..b966eaaead 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/encryption/encryption_utils.py @@ -1,49 +1,4 @@ -""" -Utility class for encryption-related operations. - -Code Example ------------- - -.. code-block:: python - - from human_protocol_sdk.encryption import EncryptionUtils - - public_key2 = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZKKJZRYJKwYBBAHaRw8BAQdAiy9Cvf7Stb5uGaPWTxhk2kEWgwHI75PK - JAN1Re+mZ/7NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSiiWUE - CwkHCAkQLJTUgF16PUcDFQgKBBYAAgECGQECGwMCHgEWIQRHZsSFAPBxClHV - TEYslNSAXXo9RwAAUYYA+gJKoCHiEl/1AUNKZrWBmvS3J9BRAFgvGHFmUKSQ - qvCJAP9+M55C/K0QjO1B9N14TPsnENaB0IIlvavhNUgKow9sBc44BGSiiWUS - CisGAQQBl1UBBQEBB0DWVuH+76KUCwGbLNnrTAGxysoo6TWpkG1upYQvZztB - cgMBCAfCeAQYFggAKgUCZKKJZQkQLJTUgF16PUcCGwwWIQRHZsSFAPBxClHV - TEYslNSAXXo9RwAA0dMBAJ0cd1OM/yWJdaVQcPp4iQOFh7hAOZlcOPF2NTRr - 1AvDAQC4Xx6swMIiu2Nx/2JYXr3QdUO/tBtC/QvU8LPQETo9Cg== - =4PJh - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - public_key3 = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZKLMDhYJKwYBBAHaRw8BAQdAufXwhFItFe4j2IuTa3Yc4lZMNAxV/B+k - X8mJ5PzqY4fNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSizA4E - CwkHCAkQsGTIZV9ne20DFQgKBBYAAgECGQECGwMCHgEWIQTviv8XOCeYpubG - OoWwZMhlX2d7bQAAYAUA/35sTPhzQjm7uPpSTw2ahUfRijlxfKRWc5p36x0L - NX+mAQCxwUgrbR2ngZOa5E+AQM8tyq8fh1qMvrM5hNeNRNf/Cc44BGSizA4S - CisGAQQBl1UBBQEBB0D8B9TjjY+KyoYR9wUE1tCaCi1N4ZoGFKscey3H5y80 - AAMBCAfCeAQYFggAKgUCZKLMDgkQsGTIZV9ne20CGwwWIQTviv8XOCeYpubG - OoWwZMhlX2d7bQAARg0BAMuQnhXzyIbbARtV3dobO7nw+VwCHVs9E7OtzLUi - 25TEAP4m0jWfjq8w+0dM9U+/+r1FqMk/q7RU8Ib8HJXUOMaGBw== - =62qY - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - encrypted_message = EncryptionUtils.encrypt( - "MESSAGE", - [public_key2, public_key3] - ) - -Module ------- -""" +"""Utility helpers for PGP encryption tasks.""" from typing import List @@ -53,57 +8,39 @@ class EncryptionUtils: - """ - A utility class that provides additional encryption-related functionalities. + """Utility class providing static methods for PGP encryption operations. + + This class offers helper methods for encrypting messages, verifying signatures, + extracting signed data, and checking message encryption status without requiring + a private key instance. """ @staticmethod def encrypt(message: str, public_keys: List[str]) -> str: - """ - Encrypts a message using the recipient's public keys. - - :param message: Message to encrypt - :param public_keys: List of armored public keys of the recipients - - :return: Armored and encrypted message - - :example: - .. code-block:: python - - from human_protocol_sdk.encryption import EncryptionUtils - - public_key2 = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZKKJZRYJKwYBBAHaRw8BAQdAiy9Cvf7Stb5uGaPWTxhk2kEWgwHI75PK - JAN1Re+mZ/7NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSiiWUE - CwkHCAkQLJTUgF16PUcDFQgKBBYAAgECGQECGwMCHgEWIQRHZsSFAPBxClHV - TEYslNSAXXo9RwAAUYYA+gJKoCHiEl/1AUNKZrWBmvS3J9BRAFgvGHFmUKSQ - qvCJAP9+M55C/K0QjO1B9N14TPsnENaB0IIlvavhNUgKow9sBc44BGSiiWUS - CisGAQQBl1UBBQEBB0DWVuH+76KUCwGbLNnrTAGxysoo6TWpkG1upYQvZztB - cgMBCAfCeAQYFggAKgUCZKKJZQkQLJTUgF16PUcCGwwWIQRHZsSFAPBxClHV - TEYslNSAXXo9RwAA0dMBAJ0cd1OM/yWJdaVQcPp4iQOFh7hAOZlcOPF2NTRr - 1AvDAQC4Xx6swMIiu2Nx/2JYXr3QdUO/tBtC/QvU8LPQETo9Cg== - =4PJh - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - public_key3 = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZKLMDhYJKwYBBAHaRw8BAQdAufXwhFItFe4j2IuTa3Yc4lZMNAxV/B+k - X8mJ5PzqY4fNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSizA4E - CwkHCAkQsGTIZV9ne20DFQgKBBYAAgECGQECGwMCHgEWIQTviv8XOCeYpubG - OoWwZMhlX2d7bQAAYAUA/35sTPhzQjm7uPpSTw2ahUfRijlxfKRWc5p36x0L - NX+mAQCxwUgrbR2ngZOa5E+AQM8tyq8fh1qMvrM5hNeNRNf/Cc44BGSizA4S - CisGAQQBl1UBBQEBB0D8B9TjjY+KyoYR9wUE1tCaCi1N4ZoGFKscey3H5y80 - AAMBCAfCeAQYFggAKgUCZKLMDgkQsGTIZV9ne20CGwwWIQTviv8XOCeYpubG - OoWwZMhlX2d7bQAARg0BAMuQnhXzyIbbARtV3dobO7nw+VwCHVs9E7OtzLUi - 25TEAP4m0jWfjq8w+0dM9U+/+r1FqMk/q7RU8Ib8HJXUOMaGBw== - =62qY - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - encrypted_message = EncryptionUtils.encrypt( - "MESSAGE", - [public_key2, public_key3] - ) + """Encrypt a message using recipient public keys. + + Encrypts a message so that only holders of the corresponding private keys + can decrypt it. Does not sign the message. + + Args: + message (str): Plain text message to encrypt. + public_keys (List[str]): List of armored PGP public keys of the recipients. + + Returns: + Armored encrypted PGP message. + + Raises: + PGPError: If encryption fails or public keys are invalid. + + Example: + ```python + from human_protocol_sdk.encryption import EncryptionUtils + + encrypted_message = EncryptionUtils.encrypt( + "MESSAGE", + ["-----BEGIN PGP PUBLIC KEY BLOCK-----..."], + ) + ``` """ pgp_message = PGPMessage.new(message) cipher = SymmetricKeyAlgorithm.AES256 @@ -118,57 +55,27 @@ def encrypt(message: str, public_keys: List[str]) -> str: @staticmethod def verify(message: str, public_key: str) -> bool: - """ - Verifies the signature of a message using the corresponding public key. - - :param message: Armored message to verify - :param public_key: Armored public key - - :return: True if the signature is valid, False otherwise - - :example: - .. code-block:: python - - from human_protocol_sdk.encryption import Encryption, EncryptionUtils - - private_key3 = \"\"\"-----BEGIN PGP PRIVATE KEY BLOCK----- - - xYYEZKLMDhYJKwYBBAHaRw8BAQdAufXwhFItFe4j2IuTa3Yc4lZMNAxV/B+k - X8mJ5PzqY4f+CQMISyqDKFlj2s/gu7LzRcFRveVbtXvQJ6lvwWEpUgkc0NAL - HykIe1gLJhsoR+v5J5fXTYwDridyL4YPLJCp7yF1K3FtyOV8Cqg46N5ijbGd - Gs0USHVtYW4gPGh1bWFuQGhtdC5haT7CjAQQFgoAPgUCZKLMDgQLCQcICRCw - ZMhlX2d7bQMVCAoEFgACAQIZAQIbAwIeARYhBO+K/xc4J5im5sY6hbBkyGVf - Z3ttAABgBQD/fmxM+HNCObu4+lJPDZqFR9GKOXF8pFZzmnfrHQs1f6YBALHB - SCttHaeBk5rkT4BAzy3Krx+HWoy+szmE141E1/8Jx4sEZKLMDhIKKwYBBAGX - VQEFAQEHQPwH1OONj4rKhhH3BQTW0JoKLU3hmgYUqxx7LcfnLzQAAwEIB/4J - Awhl3IXvo7mhyuAZwgOcvaH1X9ijw5l/VffBLYBhtmEnvN62iNZPNashQL26 - GOhrAB/v5I1XLacKNrwNP47UVGl/jz014ZBYTPGabhGl2kVQwngEGBYIACoF - AmSizA4JELBkyGVfZ3ttAhsMFiEE74r/FzgnmKbmxjqFsGTIZV9ne20AAEYN - AQDLkJ4V88iG2wEbVd3aGzu58PlcAh1bPROzrcy1ItuUxAD+JtI1n46vMPtH - TPVPv/q9RajJP6u0VPCG/ByV1DjGhgc= - =uaJU - -----END PGP PRIVATE KEY BLOCK-----\"\"\" - - passphrase = "passphrase" - - public_key = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZJ1mYRYJKwYBBAHaRw8BAQdAGLLi15zjuVhD4eUOYR5v40kDyRb3nrkh - 0tO5pPNXBInNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSdZmEE - CwkHCAkQDJeshu98/GUDFQgKBBYAAgECGQECGwMCHgEWIQQZZA1eEqmnaHG7 - F60Ml6yG73z8ZQAAWV0A/j8dVEoSyj5CKmFjF8Ag9sJutn7HLpFMUBbS12Ok - NDAlAP4/zXDvikWGYEWNvwCKjzszWUtHMtJeMRWkoRyIZ6uRCM44BGSdZmES - CisGAQQBl1UBBQEBB0D79cQcmIgLka0k/GDJt3ZPIl7mTNPKHT67PACAPfdH - dwMBCAfCeAQYFggAKgUCZJ1mYQkQDJeshu98/GUCGwwWIQQZZA1eEqmnaHG7 - F60Ml6yG73z8ZQAAtOEA/icsnf6w3eGxLgL7BxUBythzAtq9Di1R3TI8oDxC - xAPrAQDTbR33OtLbN/vg+3YYzzfsRGEtfwZ7aJEksAvJouegCQ== - =GU20 - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - encryption = Encryption(private_key3, passphrase) - signed_message = encryption.sign("MESSAGE") - - is_valid = EncryptionUtils.verify(signed_message, public_key) + """Verify the signature of a message. + + Checks if a signed message has a valid signature from the holder of + the private key corresponding to the provided public key. + + Args: + message (str): Armored PGP message to verify. + public_key (str): Armored PGP public key to verify the signature against. + + Returns: + ``True`` if the signature is valid, ``False`` otherwise. + + Example: + ```python + from human_protocol_sdk.encryption import EncryptionUtils + + is_valid = EncryptionUtils.verify( + signed_message, + "-----BEGIN PGP PUBLIC KEY BLOCK-----..." + ) + ``` """ try: signed_message = ( @@ -182,56 +89,23 @@ def verify(message: str, public_key: str) -> bool: @staticmethod def get_signed_data(message: str) -> str: - """ - Extracts the signed data from an armored signed message. - - :param message: Armored message - - :return: Extracted signed data - - :example: - .. code-block:: python - - from human_protocol_sdk.encryption import Encryption, EncryptionUtils - - private_key3 = \"\"\"-----BEGIN PGP PRIVATE KEY BLOCK----- - - xYYEZKLMDhYJKwYBBAHaRw8BAQdAufXwhFItFe4j2IuTa3Yc4lZMNAxV/B+k - X8mJ5PzqY4f+CQMISyqDKFlj2s/gu7LzRcFRveVbtXvQJ6lvwWEpUgkc0NAL - HykIe1gLJhsoR+v5J5fXTYwDridyL4YPLJCp7yF1K3FtyOV8Cqg46N5ijbGd - Gs0USHVtYW4gPGh1bWFuQGhtdC5haT7CjAQQFgoAPgUCZKLMDgQLCQcICRCw - ZMhlX2d7bQMVCAoEFgACAQIZAQIbAwIeARYhBO+K/xc4J5im5sY6hbBkyGVf - Z3ttAABgBQD/fmxM+HNCObu4+lJPDZqFR9GKOXF8pFZzmnfrHQs1f6YBALHB - SCttHaeBk5rkT4BAzy3Krx+HWoy+szmE141E1/8Jx4sEZKLMDhIKKwYBBAGX - VQEFAQEHQPwH1OONj4rKhhH3BQTW0JoKLU3hmgYUqxx7LcfnLzQAAwEIB/4J - Awhl3IXvo7mhyuAZwgOcvaH1X9ijw5l/VffBLYBhtmEnvN62iNZPNashQL26 - GOhrAB/v5I1XLacKNrwNP47UVGl/jz014ZBYTPGabhGl2kVQwngEGBYIACoF - AmSizA4JELBkyGVfZ3ttAhsMFiEE74r/FzgnmKbmxjqFsGTIZV9ne20AAEYN - AQDLkJ4V88iG2wEbVd3aGzu58PlcAh1bPROzrcy1ItuUxAD+JtI1n46vMPtH - TPVPv/q9RajJP6u0VPCG/ByV1DjGhgc= - =uaJU - -----END PGP PRIVATE KEY BLOCK-----\"\"\" - - passphrase = "passphrase" - - public_key = \"\"\"-----BEGIN PGP PUBLIC KEY BLOCK----- - - xjMEZJ1mYRYJKwYBBAHaRw8BAQdAGLLi15zjuVhD4eUOYR5v40kDyRb3nrkh - 0tO5pPNXBInNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSdZmEE - CwkHCAkQDJeshu98/GUDFQgKBBYAAgECGQECGwMCHgEWIQQZZA1eEqmnaHG7 - F60Ml6yG73z8ZQAAWV0A/j8dVEoSyj5CKmFjF8Ag9sJutn7HLpFMUBbS12Ok - NDAlAP4/zXDvikWGYEWNvwCKjzszWUtHMtJeMRWkoRyIZ6uRCM44BGSdZmES - CisGAQQBl1UBBQEBB0D79cQcmIgLka0k/GDJt3ZPIl7mTNPKHT67PACAPfdH - dwMBCAfCeAQYFggAKgUCZJ1mYQkQDJeshu98/GUCGwwWIQQZZA1eEqmnaHG7 - F60Ml6yG73z8ZQAAtOEA/icsnf6w3eGxLgL7BxUBythzAtq9Di1R3TI8oDxC - xAPrAQDTbR33OtLbN/vg+3YYzzfsRGEtfwZ7aJEksAvJouegCQ== - =GU20 - -----END PGP PUBLIC KEY BLOCK-----\"\"\" - - encryption = Encryption(private_key3, passphrase) - signed_message = encryption.sign("MESSAGE") - - result = EncryptionUtils.get_signed_data(signed_message) + """Extract the signed data from an armored signed message. + + Retrieves the original message content from a PGP signed message without + verifying the signature. + + Args: + message (str): Armored PGP signed message. + + Returns: + Extracted message content, or ``False`` if extraction fails. + + Example: + ```python + from human_protocol_sdk.encryption import EncryptionUtils + + original_message = EncryptionUtils.get_signed_data(signed_message) + ``` """ try: signed_message = ( @@ -243,30 +117,24 @@ def get_signed_data(message: str) -> str: @staticmethod def is_encrypted(message: str) -> bool: - """ - Checks whether a provided message is encrypted or not - - :param message: Text to check - - :return: True if the message is a PGP message, False otherwise + """Check whether a message is armored and encrypted. - :example: - .. code-block:: python + Determines if the provided text is a valid PGP encrypted message by checking + the message header. - from human_protocol_sdk.encryption import EncryptionUtils + Args: + message (str): Text to check for encryption. - message_1 = "message" - message_2 = \"\"\"-----BEGIN PGP MESSAGE----- + Returns: + ``True`` if the message is a PGP encrypted message, ``False`` otherwise. - wV4Dh8BoKHkyM3YSAQdAMGVFo+Meahw422JdMyDkxPA4LXeN94bOqsS9OhYGliYw - 72HgGdhoRHrRBKmRyD+Bb2HUrGptx8YRYqYJXiFVs4ev1USt6pF/5XjH+pM0d44B - 0j0BcVevrVhjdBia8kEr74NJKB2qiPAffbFJFRE1asYqQgFTjNC60/egqfzpdRay - Tj8C+e0IXRMECIXnrOaw - =SjJh - -----END PGP MESSAGE-----\"\"\" + Example: + ```python + from human_protocol_sdk.encryption import EncryptionUtils - print("The message_1 is encrypted: ", EncryptionUtils.is_encrypted(message_1)) - print("The message_2 is encrypted: ", EncryptionUtils.is_encrypted(message_2)) + if EncryptionUtils.is_encrypted(some_text): + print("Message is encrypted") + ``` """ try: unarmored = PGPMessage.ascii_unarmor(message) diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py index 4d26bc20df..64bb1aa4de 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_client.py @@ -1,18 +1,11 @@ -""" -This client enables to perform actions on Escrow contracts and -obtain information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the web3. -To use this client, you need to create Web3 instance, and configure default account, -as well as some middlewares. - -Code Example ------------- +"""Client to perform actions on Escrow contracts and obtain information from the contracts. -* With Signer - -.. code-block:: python +Selects the network based on the Web3 chain id. Configure Web3 with an account +and signer middleware for writes; read operations work without a signer. +Examples: + With signer: + ```python from eth_typing import URI from web3 import Web3 from web3.middleware import SignAndSendRawMiddlewareBuilder @@ -33,11 +26,11 @@ def get_w3_with_priv_key(priv_key: str): (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') escrow_client = EscrowClient(w3) + ``` -* Without Signer (For read operations only) - -.. code-block:: python + Read-only: + ```python from eth_typing import URI from web3 import Web3 from web3.providers.auto import load_provider_from_uri @@ -46,9 +39,7 @@ def get_w3_with_priv_key(priv_key: str): w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) escrow_client = EscrowClient(w3) - -Module ------- + ``` """ import logging @@ -78,42 +69,51 @@ def get_w3_with_priv_key(priv_key: str): class EscrowCancel: - def __init__(self, tx_hash: str, amount_refunded: any): - """ - Represents the result of an escrow cancellation transaction. + """Represents the result of an escrow cancellation transaction. - :param tx_hash: The hash of the transaction that cancelled the escrow. - :param amount_refunded: The amount refunded during the escrow cancellation. - """ + Attributes: + txHash (str): The hash of the transaction that cancelled the escrow. + amountRefunded (int): The amount refunded during the escrow cancellation. + """ + + def __init__(self, tx_hash: str, amount_refunded: any): self.txHash = tx_hash self.amountRefunded = amount_refunded class EscrowWithdraw: - def __init__(self, tx_hash: str, token_address: str, withdrawn_amount: any): - """ - Represents the result of an escrow cancellation transaction. + """Represents the result of an escrow withdrawal transaction. - :param tx_hash: The hash of the transaction associated with the escrow withdrawal. - :param token_address: The address of the token used for the withdrawal. - :param withdrawn_amount: The amount withdrawn from the escrow. - """ + Attributes: + txHash (str): The hash of the transaction associated with the escrow withdrawal. + token_address (str): The address of the token used for the withdrawal. + withdrawn_amount (int): The amount withdrawn from the escrow. + """ + + def __init__(self, tx_hash: str, token_address: str, withdrawn_amount: any): self.txHash = tx_hash self.token_address = token_address self.withdrawn_amount = withdrawn_amount class EscrowClientError(Exception): - """ - Raises when some error happens when interacting with escrow. - """ + """Exception raised when errors occur during escrow operations.""" pass class EscrowConfig: - """ - A class used to manage escrow parameters. + """Configuration parameters for escrow setup. + + Attributes: + recording_oracle_address (str): Address of the recording oracle. + reputation_oracle_address (str): Address of the reputation oracle. + exchange_oracle_address (str): Address of the exchange oracle. + recording_oracle_fee (int): Recording oracle fee percentage (0-100). + reputation_oracle_fee (int): Reputation oracle fee percentage (0-100). + exchange_oracle_fee (int): Exchange oracle fee percentage (0-100). + manifest (str): Manifest payload (URL or JSON string). + hash (str): Manifest file hash. """ def __init__( @@ -128,14 +128,9 @@ def __init__( hash: str, ): """ - Initializes a Escrow instance. - - :param recording_oracle_address: Address of the Recording Oracle - :param reputation_oracle_address: Address of the Reputation Oracle - :param recording_oracle_fee: Fee percentage of the Recording Oracle - :param reputation_oracle_fee: Fee percentage of the Reputation Oracle - :param manifest: Manifest data (can be a URL or JSON string) - :param hash: Manifest file hash + Raises: + EscrowClientError: If addresses are invalid, fees are out of range, + total fees exceed 100%, or manifest data is invalid. """ if not Web3.is_address(recording_oracle_address): raise EscrowClientError( @@ -174,15 +169,27 @@ def __init__( class EscrowClient: - """ - A client class to interact with the escrow smart contract. + """A client for interacting with escrow smart contracts. + + This client provides methods to create, fund, configure, and manage escrow contracts + on the Human Protocol network. It handles transaction signing, validation, and + event processing for escrow operations. + + Attributes: + w3 (Web3): Web3 instance configured for the target network. + network (dict): Network configuration for the current chain. + factory_contract (Contract): Contract instance for the escrow factory. """ def __init__(self, web3: Web3): - """ - Initializes a Escrow instance. + """Initialize an EscrowClient instance. + + Args: + web3 (Web3): Web3 instance configured for the target network. + Must have a valid provider and chain ID. - :param web3: The Web3 object + Raises: + EscrowClientError: If chain ID is invalid or network configuration is missing. """ # Initialize web3 instance @@ -216,46 +223,26 @@ def create_escrow( job_requester_id: str, tx_options: Optional[TxParams] = None, ) -> str: - """ - Creates a new escrow contract. - - :param token_address: Address of the token to be used in the escrow - :param job_requester_id: An off-chain identifier for the job requester - :param tx_options: (Optional) Transaction options - - :return: Address of the created escrow contract - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri( - URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - token_address = '0x1234567890abcdef1234567890abcdef12345678' - job_requester_id = 'job-requester' - escrow_address = escrow_client.create_escrow( - token_address, - job_requester_id - ) + """Create a new escrow contract. + + Args: + token_address (str): ERC-20 token address to fund the escrow. + job_requester_id (str): Off-chain identifier for the job requester. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + Address of the newly created escrow contract. + + Raises: + EscrowClientError: If the token address is invalid or the transaction fails. + + Example: + ```python + escrow_address = escrow_client.create_escrow( + "0x1234567890abcdef1234567890abcdef12345678", + "job-requester", + ) + ``` """ if not Web3.is_address(token_address): raise EscrowClientError(f"Invalid token address: {token_address}") @@ -286,65 +273,34 @@ def create_fund_and_setup_escrow( escrow_config: EscrowConfig, tx_options: Optional[TxParams] = None, ) -> str: - """ - Creates, funds, and sets up a new escrow contract in a single transaction. - - :param token_address: Address of the token to be used in the escrow - :param amount: The token amount to fund the escrow with - :param job_requester_id: An off-chain identifier for the job requester - :param escrow_config: Configuration parameters for escrow setup - :param tx_options: (Optional) Transaction options - - :return: Address of the created escrow contract - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri( - URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - token_address = '0x1234567890abcdef1234567890abcdef12345678' - job_requester_id = 'job-requester' - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - escrow_config = EscrowConfig( - recording_oracle_address='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - reputation_oracle_address='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - exchange_oracle_address='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - recording_oracle_fee=100, - reputation_oracle_fee=100, - exchange_oracle_fee=100, - recording_oracle_url='https://example.com/recording', - reputation_oracle_url='https://example.com/reputation', - exchange_oracle_url='https://example.com/exchange', - manifest_url='https://example.com/manifest', - manifest_hash='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef' - ) - - escrow_address = escrow_client.create_fund_and_setup_escrow( - token_address, - amount, - job_requester_id, - escrow_config - ) + """Create, fund, and configure an escrow in a single transaction. + + This is a convenience method that combines escrow creation, funding, and setup + into one atomic operation. + + Args: + token_address (str): ERC-20 token address to fund the escrow. + amount (int): Token amount to fund (in token's smallest unit). + job_requester_id (str): Off-chain identifier for the job requester. + escrow_config (EscrowConfig): Escrow configuration parameters including + oracle addresses, fees, and manifest data. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + Address of the newly created and configured escrow contract. + + Raises: + EscrowClientError: If inputs are invalid or the transaction fails. + + Example: + ```python + escrow_address = escrow_client.create_fund_and_setup_escrow( + "0x1234567890abcdef1234567890abcdef12345678", + Web3.to_wei(5, "ether"), + "job-requester", + escrow_config, + ) + ``` """ if not Web3.is_address(token_address): raise EscrowClientError(f"Invalid token address: {token_address}") @@ -383,56 +339,26 @@ def setup( escrow_config: EscrowConfig, tx_options: Optional[TxParams] = None, ) -> None: - """ - Sets up the parameters of the escrow. - - :param escrow_address: Address of the escrow contract - :param escrow_config: Configuration parameters for the escrow - :param tx_options: (Optional) Transaction options - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri( - URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - escrow_address = "0x1234567890abcdef1234567890abcdef12345678" - escrow_config = EscrowConfig( - recording_oracle_address='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - reputation_oracle_address='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - exchange_oracle_address='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - recording_oracle_fee=100, - reputation_oracle_fee=100, - exchange_oracle_fee=100, - recording_oracle_url='https://example.com/recording', - reputation_oracle_url='https://example.com/reputation', - exchange_oracle_url='https://example.com/exchange', - manifest_url='https://example.com/manifest', - manifest_hash='0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef' - ) - escrow_client.setup( - escrow_address, - escrow_config - ) + """Set escrow roles, fees, and manifest metadata. + + Configures the escrow with oracle addresses, fee percentages, and manifest information. + + Args: + escrow_address (str): Address of the escrow contract to configure. + escrow_config (EscrowConfig): Escrow configuration parameters including + oracle addresses, fees, and manifest data. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + None + + Raises: + EscrowClientError: If the escrow address is invalid or the transaction fails. + + Example: + ```python + escrow_client.setup("0xYourEscrow", escrow_config) + ``` """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -463,45 +389,26 @@ def fund( amount: int, tx_options: Optional[TxParams] = None, ) -> None: - """ - Adds funds to the escrow. - - :param escrow_address: Address of the escrow to fund - :param amount: Amount to be added as funds - :param tx_options: (Optional) Additional transaction parameters - - :return: None + """Add funds to the escrow. - :raise EscrowClientError: If an error occurs while checking the parameters + Transfers tokens from the caller's account to the escrow contract. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow to fund. + amount (int): Amount of tokens to transfer (must be positive, in token's smallest unit). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Returns: + None - from human_protocol_sdk.escrow import EscrowClient + Raises: + EscrowClientError: If inputs are invalid or the transfer fails. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - escrow_client.fund( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f", amount - ) + Example: + ```python + amount = Web3.to_wei(5, "ether") + escrow_client.fund("0x62dD51230A30401C455c8398d06F85e4EaB6309f", amount) + ``` """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -529,48 +436,33 @@ def store_results( funds_to_reserve: Optional[int] = None, tx_options: Optional[TxParams] = None, ) -> None: - """ - Stores the results URL and hash, with optional funds to reserve. - - :param escrow_address: Address of the escrow - :param url: Results file URL - :param hash: Results file hash - :param funds_to_reserve: (Optional) Funds to reserve for payouts - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - escrow_client.store_results( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f", - "http://localhost/results.json", - "b5dad76bf6772c0f07fd5e048f6e75a5f86ee079" - ) + """Store results URL and hash, with optional funds reservation. + + Stores the intermediate or final results location and hash. Optionally reserves + funds for future payouts. + + Args: + escrow_address (str): Address of the escrow. + url (str): Results file URL. + hash (str): Results file hash. + funds_to_reserve (Optional[int]): Optional funds to reserve for payouts. + If None, uses legacy signature without reservation. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + None + + Raises: + EscrowClientError: If validation fails or the transaction reverts. + + Example: + ```python + escrow_client.store_results( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + "http://localhost/results.json", + "b5dad76bf6772c0f07fd5e048f6e75a5f86ee079", + ) + ``` """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -614,41 +506,24 @@ def get_w3_with_priv_key(priv_key: str): def complete( self, escrow_address: str, tx_options: Optional[TxParams] = None ) -> None: - """ - Sets the status of an escrow to completed. - - :param escrow_address: Address of the escrow to complete - :param tx_options: (Optional) Additional transaction parameters - - :return: None + """Set the status of an escrow to completed. - :raise EscrowClientError: If an error occurs while checking the parameters + Marks the escrow as completed, preventing further modifications. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow to complete. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Returns: + None - from human_protocol_sdk.escrow import EscrowClient + Raises: + EscrowClientError: If validation fails or the transaction reverts. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - escrow_client.complete("0x62dD51230A30401C455c8398d06F85e4EaB6309f") + Example: + ```python + escrow_client.complete("0x62dD51230A30401C455c8398d06F85e4EaB6309f") + ``` """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -675,65 +550,40 @@ def bulk_payout( force_complete: bool, tx_options: Optional[TxParams] = None, ) -> None: - """ - Pays out to recipients, supporting both payoutId (str) and txId (int) signatures and sets the URL of the final results file. - - :param escrow_address: Address of the escrow - :param recipients: List of recipient addresses - :param amounts: List of amounts - :param final_results_url: Final results file URL - :param final_results_hash: Final results file hash - :param payout_id: Payout ID (str) or Transaction ID (int) - :param force_complete: (Optional) Whether to force completion - :param tx_options: (Optional) Transaction options - - :return: None - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - recipients = [ - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92267' - ] - amounts = [ - Web3.to_wei(5, 'ether'), - Web3.to_wei(10, 'ether') - ] - results_url = 'http://localhost/results.json' - results_hash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079' - - escrow_client.bulk_payout( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f", - recipients, - amounts, - results_url, - results_hash, - 1 - ) + """Distribute payouts to recipients and set final results. + + Performs bulk payment distribution to multiple recipients and records the final + results URL and hash. + + Args: + escrow_address (str): Address of the escrow. + recipients (List[str]): List of recipient addresses. + amounts (List[int]): Token amounts for each recipient (in token's smallest unit). + final_results_url (str): Final results file URL. + final_results_hash (str): Final results file hash. + payout_id (Union[str, int]): Payout identifier. String for newer contracts, + integer transaction ID for older contracts. + force_complete (bool): Whether to force completion after payout (if supported). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + None + + Raises: + EscrowClientError: If validation fails or the transaction reverts. + + Example: + ```python + escrow_client.bulk_payout( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"], + [Web3.to_wei(5, "ether")], + "http://localhost/results.json", + "b5dad76bf6772c0f07fd5e048f6e75a5f86ee079", + payout_id="payout-1", + force_complete=True, + ) + ``` """ self.ensure_correct_bulk_payout_input( escrow_address, recipients, amounts, final_results_url, final_results_hash @@ -784,77 +634,42 @@ def create_bulk_payout_transaction( force_complete: Optional[bool] = False, tx_options: Optional[TxParams] = None, ) -> TxParams: - """ - Creates a prepared transaction for bulk payout without signing or sending it. - - :param escrow_address: Address of the escrow - :param recipients: Array of recipient addresses - :param amounts: Array of amounts the recipients will receive - :param final_results_url: Final results file URL - :param final_results_hash: Final results file hash - :param payoutId: Unique identifier for the payout - :param tx_options: (Optional) Additional transaction parameters - - :return: A dictionary containing the prepared transaction - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - recipients = [ - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92267' - ] - amounts = [ - Web3.to_wei(5, 'ether'), - Web3.to_wei(10, 'ether') - ] - results_url = 'http://localhost/results.json' - results_hash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079' - - transaction = escrow_client.create_bulk_payout_transaction( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f", - recipients, - amounts, - results_url, - results_hash, - 1, - false - ) - - print(f"Transaction: {transaction}") - - signed_transaction = w3.eth.account.sign_transaction( - transaction, private_key - ) - tx_hash = w3.eth.send_raw_transaction( - signed_transaction.raw_transaction - ) - tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) - print(f"Transaction sent with hash: {tx_hash.hex()}") - print(f"Transaction receipt: {tx_receipt}") + """Prepare an unsigned bulk payout transaction. + + Creates a transaction dictionary that can be signed and sent externally. + Useful for offline signing or custom transaction handling. + + Args: + escrow_address (str): Address of the escrow. + recipients (List[str]): List of recipient addresses. + amounts (List[int]): Token amounts for each recipient (in token's smallest unit). + final_results_url (str): Final results file URL. + final_results_hash (str): Final results file hash. + payoutId (str): Unique identifier for the payout (string signature). + force_complete (Optional[bool]): Whether to force completion after payout. Defaults to False. + tx_options (Optional[TxParams]): Optional transaction parameters to seed the transaction. + + Returns: + A populated transaction dictionary ready to sign and send, + including nonce, gas estimate, gas price/fees, and chain ID. + + Raises: + EscrowClientError: If validation fails. + + Example: + ```python + tx = escrow_client.create_bulk_payout_transaction( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"], + [Web3.to_wei(5, "ether")], + "http://localhost/results.json", + "b5dad76bf6772c0f07fd5e048f6e75a5f86ee079", + "payout-1", + force_complete=False, + ) + signed = w3.eth.account.sign_transaction(tx, "PRIVATE_KEY") + w3.eth.send_raw_transaction(signed.raw_transaction) + ``` """ self.ensure_correct_bulk_payout_input( escrow_address, recipients, amounts, final_results_url, final_results_hash @@ -904,18 +719,28 @@ def ensure_correct_bulk_payout_input( final_results_url: str, final_results_hash: str, ) -> None: - """ - Validates input parameters for bulk payout operations. - - :param escrow_address: Address of the escrow - :param recipients: Array of recipient addresses - :param amounts: Array of amounts the recipients will receive - :param final_results_url: Final results file URL - :param final_results_hash: Final results file hash - - :return: None - - :raise EscrowClientError: If validation fails + """Validate inputs for bulk payout operations. + + Performs comprehensive validation of all bulk payout parameters including + address validity, array lengths, amounts, and escrow balance. + + Args: + escrow_address (str): Address of the escrow. + recipients (List[str]): List of recipient addresses. + amounts (List[int]): Token amounts for each recipient (in token's smallest unit). + final_results_url (str): Final results file URL. + final_results_hash (str): Final results file hash. + + Returns: + None + + Raises: + EscrowClientError: If any parameter is invalid, including: + - Invalid escrow or recipient addresses + - Empty or mismatched arrays + - Too many recipients (exceeds maximum) + - Invalid amounts (negative, zero, or exceeding escrow balance) + - Invalid URL or hash """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -947,38 +772,27 @@ def ensure_correct_bulk_payout_input( def request_cancellation( self, escrow_address: str, tx_options: Optional[TxParams] = None ) -> None: - """Requests the cancellation of the specified escrow (moves status to ToCancel or finalizes if expired). + """Request cancellation of the specified escrow. - :param escrow_address: Address of the escrow to request cancellation - :param tx_options: (Optional) Additional transaction parameters + Initiates the cancellation process. If the escrow is expired, it may finalize + immediately; otherwise, it transitions to ToCancel status. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow to request cancellation. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Returns: + None - from human_protocol_sdk.escrow import EscrowClient + Raises: + EscrowClientError: If validation fails or the transaction reverts. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - escrow_client.request_cancellation( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Example: + ```python + escrow_client.request_cancellation( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f" + ) + ``` """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -997,47 +811,26 @@ def get_w3_with_priv_key(priv_key: str): def cancel( self, escrow_address: str, tx_options: Optional[TxParams] = None ) -> EscrowCancel: - """ - Cancels the specified escrow and sends the balance to the canceler. - - :param escrow_address: Address of the escrow to cancel - :param tx_options: (Optional) Additional transaction parameters - - :return: EscrowCancel: - An instance of the EscrowCancel class containing details of the cancellation transaction, - including the transaction hash and the amount refunded. - - :raise EscrowClientError: If an error occurs while checking the parameters - :raise EscrowClientError: If the transfer event associated with the cancellation - is not found in the transaction logs - - :example: - .. code-block:: python + """Cancel the specified escrow and refund the balance. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Finalizes the cancellation and transfers remaining funds to the canceler. - from human_protocol_sdk.escrow import EscrowClient + Args: + escrow_address (str): Address of the escrow to cancel. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) + Returns: + Cancellation details including transaction hash and refunded amount. - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) + Raises: + EscrowClientError: If validation fails or the transfer event is missing. - escrow_cancel_data = escrow_client.cancel( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Example: + ```python + escrow_cancel_data = escrow_client.cancel( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f" + ) + ``` """ if not Web3.is_address(escrow_address): raise EscrowClientError(f"Invalid escrow address: {escrow_address}") @@ -1059,49 +852,29 @@ def withdraw( token_address: str, tx_options: Optional[TxParams] = None, ) -> EscrowWithdraw: - """ - Withdraws additional tokens in the escrow to the canceler. - - :param escrow_address: Address of the escrow to withdraw - :param token_address: Address of the token to withdraw - :param tx_options: (Optional) Additional transaction parameters - - :return: EscrowWithdraw: - An instance of the EscrowWithdraw class containing details of the withdrawal transaction, - including the transaction hash and the token address and amount withdrawn. - - :raise EscrowClientError: If an error occurs while checking the parameters - :raise EscrowClientError: If the transfer event associated with the withdrawal - is not found in the transaction logs - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - escrow_client = EscrowClient(w3) - - escrow_cancel_data = escrow_client.withdraw( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f", - "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4" - ) + """Withdraw additional tokens from the escrow. + + Withdraws tokens (other than the primary escrow token) to the canceler's address. + Useful for recovering accidentally sent tokens. + + Args: + escrow_address (str): Address of the escrow to withdraw from. + token_address (str): Address of the token to withdraw. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + Withdrawal details including transaction hash, token address, and amount. + + Raises: + EscrowClientError: If validation fails or transfer event is missing. + + Example: + ```python + withdrawal = escrow_client.withdraw( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + "0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4", + ) + ``` """ if not Web3.is_address(escrow_address): @@ -1146,30 +919,18 @@ def get_w3_with_priv_key(priv_key: str): handle_error(e, EscrowClientError) def get_balance(self, escrow_address: str) -> int: - """ - Gets the balance for a specified escrow address. + """Get the remaining balance for a specified escrow. - :param escrow_address: Address of the escrow + Queries the current available balance in the escrow that can be used for payouts. - :return: Value of the balance + Args: + escrow_address (str): Address of the escrow. - :raise EscrowClientError: If an error occurs while checking the parameters + Returns: + Remaining escrow balance in token's smallest unit. - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - balance = escrow_client.get_balance( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1188,30 +949,18 @@ def get_balance(self, escrow_address: str) -> int: return self._get_escrow_contract(escrow_address).functions.getBalance().call() def get_reserved_funds(self, escrow_address: str) -> int: - """ - Gets the reserved funds for a specified escrow address. + """Get the reserved funds for a specified escrow. - :param escrow_address: Address of the escrow + Queries the amount of funds that have been reserved for future payouts. - :return: Value of the reserved funds + Args: + escrow_address (str): Address of the escrow. - :raise EscrowClientError: If an error occurs while checking the parameters + Returns: + Reserved funds amount in token's smallest unit. - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - reserved_funds = escrow_client.get_reserved_funds( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1222,30 +971,18 @@ def get_reserved_funds(self, escrow_address: str) -> int: ) def get_manifest_hash(self, escrow_address: str) -> str: - """ - Gets the manifest file hash. + """Get the manifest file hash. - :param escrow_address: Address of the escrow + Retrieves the hash of the manifest that defines the job requirements. - :return: Manifest file hash + Args: + escrow_address (str): Address of the escrow. - :raise EscrowClientError: If an error occurs while checking the parameters + Returns: + Manifest file hash. - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - manifest_hash = escrow_client.get_manifest_hash( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1254,30 +991,18 @@ def get_manifest_hash(self, escrow_address: str) -> str: return self._get_escrow_contract(escrow_address).functions.manifestHash().call() def get_manifest(self, escrow_address: str) -> str: - """ - Gets the manifest data (can be a URL or JSON string). - - :param escrow_address: Address of the escrow - - :return str: Manifest data + """Get the manifest data. - :raise EscrowClientError: If an error occurs while checking the parameters + Retrieves the manifest URL or JSON string that defines the job requirements. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Returns: + str: Manifest data (URL or JSON string). - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - manifest = escrow_client.get_manifest( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1286,30 +1011,18 @@ def get_manifest(self, escrow_address: str) -> str: return self._get_escrow_contract(escrow_address).functions.manifestUrl().call() def get_results_url(self, escrow_address: str) -> str: - """ - Gets the results file URL. - - :param escrow_address: Address of the escrow - - :return: Results file url + """Get the final results file URL. - :raise EscrowClientError: If an error occurs while checking the parameters + Retrieves the URL where final results are stored. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Returns: + Final results URL. - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - url = escrow_client.get_results_url( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1320,30 +1033,18 @@ def get_results_url(self, escrow_address: str) -> str: ) def get_intermediate_results_url(self, escrow_address: str) -> str: - """ - Gets the intermediate results file URL. - - :param escrow_address: Address of the escrow - - :return: Intermediate results file url + """Get the intermediate results file URL. - :raise EscrowClientError: If an error occurs while checking the parameters + Retrieves the URL where intermediate results are stored. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Returns: + Intermediate results URL. - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - url = escrow_client.get_intermediate_results_url( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1356,30 +1057,18 @@ def get_intermediate_results_url(self, escrow_address: str) -> str: ) def get_intermediate_results_hash(self, escrow_address: str) -> str: - """ - Gets the intermediate results file hash. - - :param escrow_address: Address of the escrow - - :return: Intermediate results file hash - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python + """Get the intermediate results file hash. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Retrieves the hash of the intermediate results file. - from human_protocol_sdk.escrow import EscrowClient + Args: + escrow_address (str): Address of the escrow. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) + Returns: + Intermediate results file hash. - hash = escrow_client.get_intermediate_results_hash( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1392,30 +1081,18 @@ def get_intermediate_results_hash(self, escrow_address: str) -> str: ) def get_token_address(self, escrow_address: str) -> str: - """ - Gets the address of the token used to fund the escrow. - - :param escrow_address: Address of the escrow - - :return: Address of the token - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python + """Get the token address used to fund the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Retrieves the ERC-20 token contract address used for this escrow. - from human_protocol_sdk.escrow import EscrowClient + Args: + escrow_address (str): Address of the escrow. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) + Returns: + Token address used to fund the escrow. - token_address = escrow_client.get_token_address( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1424,30 +1101,18 @@ def get_token_address(self, escrow_address: str) -> str: return self._get_escrow_contract(escrow_address).functions.token().call() def get_status(self, escrow_address: str) -> Status: - """ - Gets the current status of the escrow. - - :param escrow_address: Address of the escrow - - :return: Current escrow status - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python + """Get the current status of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Retrieves the current state of the escrow (e.g., Launched, Pending, Completed). - from human_protocol_sdk.escrow import EscrowClient + Args: + escrow_address (str): Address of the escrow. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) + Returns: + Current escrow status enum value. - status = escrow_client.get_status( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1458,30 +1123,18 @@ def get_status(self, escrow_address: str) -> Status: ) def get_recording_oracle_address(self, escrow_address: str) -> str: - """ - Gets the recording oracle address of the escrow. - - :param escrow_address: Address of the escrow - - :return: Recording oracle address - - :raise EscrowClientError: If an error occurs while checking the parameters - - :example: - .. code-block:: python + """Get the recording oracle address of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Retrieves the address of the oracle responsible for recording job results. - from human_protocol_sdk.escrow import EscrowClient + Args: + escrow_address (str): Address of the escrow. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) + Returns: + Recording oracle address. - recording_oracle = escrow_client.get_recording_oracle_address( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1492,30 +1145,18 @@ def get_recording_oracle_address(self, escrow_address: str) -> str: ) def get_reputation_oracle_address(self, escrow_address: str) -> str: - """ - Gets the reputation oracle address of the escrow. - - :param escrow_address: Address of the escrow - - :return: Reputation oracle address - - :raise EscrowClientError: If an error occurs while checking the parameters + """Get the reputation oracle address of the escrow. - :example: - .. code-block:: python + Retrieves the address of the oracle responsible for reputation tracking. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Args: + escrow_address (str): Address of the escrow. - from human_protocol_sdk.escrow import EscrowClient + Returns: + Reputation oracle address. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - reputation_oracle = escrow_client.get_reputation_oracle_address( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1528,30 +1169,18 @@ def get_reputation_oracle_address(self, escrow_address: str) -> str: ) def get_exchange_oracle_address(self, escrow_address: str) -> str: - """ - Gets the exchange oracle address of the escrow. - - :param escrow_address: Address of the escrow - - :return: Exchange oracle address - - :raise EscrowClientError: If an error occurs while checking the parameters + """Get the exchange oracle address of the escrow. - :example: - .. code-block:: python + Retrieves the address of the oracle responsible for exchange rate data. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Args: + escrow_address (str): Address of the escrow. - from human_protocol_sdk.escrow import EscrowClient + Returns: + Exchange oracle address. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - exchange_oracle = escrow_client.get_exchange_oracle_address( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1562,30 +1191,18 @@ def get_exchange_oracle_address(self, escrow_address: str) -> str: ) def get_job_launcher_address(self, escrow_address: str) -> str: - """ - Gets the job launcher address of the escrow. - - :param escrow_address: Address of the escrow - - :return: Job launcher address + """Get the job launcher address of the escrow. - :raise EscrowClientError: If an error occurs while checking the parameters + Retrieves the address of the account that launched/created this escrow. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Returns: + Job launcher address. - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - job_launcher = escrow_client.get_job_launcher_address( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1594,30 +1211,18 @@ def get_job_launcher_address(self, escrow_address: str) -> str: return self._get_escrow_contract(escrow_address).functions.launcher().call() def get_factory_address(self, escrow_address: str) -> str: - """ - Gets the escrow factory address of the escrow. - - :param escrow_address: Address of the escrow - - :return: Escrow factory address + """Get the escrow factory address of the escrow. - :raise EscrowClientError: If an error occurs while checking the parameters + Retrieves the address of the factory contract that created this escrow. - :example: - .. code-block:: python + Args: + escrow_address (str): Address of the escrow. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Returns: + Escrow factory address. - from human_protocol_sdk.escrow import EscrowClient - - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - escrow_client = EscrowClient(w3) - - escrow_factory = escrow_client.get_factory_address( - "0x62dD51230A30401C455c8398d06F85e4EaB6309f" - ) + Raises: + EscrowClientError: If the escrow address is invalid. """ if not Web3.is_address(escrow_address): @@ -1628,13 +1233,19 @@ def get_factory_address(self, escrow_address: str) -> str: ) def _get_escrow_contract(self, address: str) -> contract.Contract: - """ - Returns the escrow contract instance. + """Get the escrow contract instance. + + Internal method to retrieve a contract instance for the given escrow address. + Validates that the address is a valid escrow from the factory. - :param escrow_address: Address of the deployed escrow + Args: + address (str): Address of the deployed escrow. - :return: The instance of the escrow contract + Returns: + The instance of the escrow contract. + Raises: + EscrowClientError: If the address is not a valid escrow from the factory. """ if not self.factory_contract.functions.hasEscrow(address): diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_utils.py index 5a5531e591..fa759799d1 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_utils.py @@ -1,11 +1,7 @@ -""" -Utility class for escrow-related operations. - -Code Example ------------- - -.. code-block:: python +"""Utility helpers for escrow-related queries. +Example: + ```python from human_protocol_sdk.constants import ChainId from human_protocol_sdk.escrow import EscrowUtils, EscrowFilter, Status @@ -19,9 +15,7 @@ ) ) ) - -Module ------- + ``` """ import logging @@ -47,6 +41,36 @@ class EscrowData: + """Represents escrow data retrieved from the subgraph. + + Attributes: + id (str): Unique escrow identifier. + address (str): Escrow contract address. + amount_paid (int): Total amount paid out. + balance (int): Remaining balance in the escrow. + count (int): Number of payouts executed. + factory_address (str): Address of the factory that created this escrow. + final_results_url (Optional[str]): URL for final results file. + final_results_hash (Optional[str]): Hash of final results file. + intermediate_results_url (Optional[str]): URL for intermediate results file. + intermediate_results_hash (Optional[str]): Hash of intermediate results file. + launcher (str): Address of the job launcher. + job_requester_id (Optional[str]): Off-chain job requester identifier. + manifest_hash (Optional[str]): Hash of the manifest file. + manifest (Optional[str]): Manifest data (URL or JSON string). + recording_oracle (Optional[str]): Address of the recording oracle. + reputation_oracle (Optional[str]): Address of the reputation oracle. + exchange_oracle (Optional[str]): Address of the exchange oracle. + recording_oracle_fee (Optional[int]): Recording oracle fee percentage. + reputation_oracle_fee (Optional[int]): Reputation oracle fee percentage. + exchange_oracle_fee (Optional[int]): Exchange oracle fee percentage. + status (str): Current escrow status. + token (str): Address of the payment token. + total_funded_amount (int): Total amount funded to the escrow. + created_at (int): Creation timestamp in milliseconds. + chain_id (ChainId): Chain where the escrow is deployed. + """ + def __init__( self, chain_id: ChainId, @@ -75,36 +99,6 @@ def __init__( reputation_oracle_fee: Optional[str] = None, exchange_oracle_fee: Optional[str] = None, ): - """ - Initializes an EscrowData instance. - - :param chain_id: Chain identifier - :param id: Identifier - :param address: Address - :param amount_paid: Amount paid - :param balance: Balance - :param count: Count - :param factory_address: Factory address - :param launcher: Launcher - :param job_requester_id: Job requester identifier - :param status: Status - :param token: Token - :param total_funded_amount: Total funded amount - :param created_at: Creation timestamp in milliseconds - :param final_results_url: URL for final results. - :param final_results_hash: Hash for final results. - :param intermediate_results_url: URL for intermediate results. - :param intermediate_results_hash: Hash for intermediate results. - :param manifest_hash: Manifest hash. - :param manifest: Manifest data (JSON/URL). - :param recording_oracle: Recording Oracle address. - :param reputation_oracle: Reputation Oracle address. - :param exchange_oracle: Exchange Oracle address. - :param recording_oracle_fee: Fee for the Recording Oracle. - :param reputation_oracle_fee: Fee for the Reputation Oracle. - :param exchange_oracle_fee: Fee for the Exchange Oracle. - """ - self.id = id self.address = address self.amount_paid = int(amount_paid) @@ -139,13 +133,13 @@ def __init__( class StatusEvent: - """ - Initializes a StatusEvent instance. + """Represents an escrow status change event. - :param timestamp: The timestamp of the event in milliseconds. - :param status: The status of the escrow. - :param chain_id: The chain identifier where the event occurred. - :param escrow_address: The address of the escrow. + Attributes: + timestamp (int): Event timestamp in milliseconds. + status (str): The new status of the escrow. + chain_id (ChainId): Chain where the event occurred. + escrow_address (str): Address of the escrow that changed status. """ def __init__( @@ -158,15 +152,14 @@ def __init__( class Payout: - """ - Initializes a Payout instance. - - :param id: The id of the payout. - :param chain_id: The chain identifier where the payout occurred. - :param escrow_address: The address of the escrow that executed the payout. - :param recipient: The address of the recipient. - :param amount: The amount of the payout. - :param created_at: The time of creation of the payout in milliseconds. + """Represents a payout distributed by an escrow. + + Attributes: + id (str): Unique payout identifier. + escrow_address (str): Address of the escrow that executed the payout. + recipient (str): Address of the payout recipient. + amount (int): Amount paid in token's smallest unit. + created_at (int): Payout creation timestamp in milliseconds. """ def __init__( @@ -180,16 +173,16 @@ def __init__( class CancellationRefund: - """ - Represents a cancellation refund event. - - :param id: The unique identifier for the cancellation refund event. - :param escrow_address: The address of the escrow associated with the refund. - :param receiver: The address of the recipient receiving the refund. - :param amount: The amount being refunded. - :param block: The block number in which the refund was processed. - :param timestamp: The timestamp of the refund event in milliseconds. - :param tx_hash: The transaction hash of the refund event. + """Represents a cancellation refund event. + + Attributes: + id (str): Unique refund identifier. + escrow_address (str): Address of the escrow associated with the refund. + receiver (str): Address receiving the refund. + amount (int): Refunded amount in token's smallest unit. + block (int): Block number where the refund was processed. + timestamp (int): Refund timestamp in milliseconds. + tx_hash (str): Transaction hash of the refund. """ def __init__( @@ -212,8 +205,10 @@ def __init__( class EscrowUtils: - """ - A utility class that provides additional escrow-related functionalities. + """Utility class providing escrow-related query and data retrieval functions. + + This class offers static methods to fetch escrow data, status events, payouts, + and cancellation refunds from the Human Protocol subgraph. """ @staticmethod @@ -221,29 +216,37 @@ def get_escrows( filter: EscrowFilter, options: Optional[SubgraphOptions] = None, ) -> List[EscrowData]: - """Get an array of escrow addresses based on the specified filter parameters. - - :param filter: Object containing all the necessary parameters to filter - :param options: Optional config for subgraph requests - - :return: List of escrows - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.escrow import EscrowUtils, EscrowFilter, Status - - print( - EscrowUtils.get_escrows( - EscrowFilter( - networks=[ChainId.POLYGON_AMOY], - status=Status.Pending, - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) + """Retrieve a list of escrows matching the provided filter criteria. + + Queries the subgraph for escrow contracts that match the specified parameters + including status, date range, and oracle addresses. + + Args: + filter (EscrowFilter): Filter parameters including chain ID, status, date range, + and oracle addresses. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests + such as custom endpoints or timeout settings. + + Returns: + A list of escrow records matching the filter criteria. + Returns an empty list if no matches are found. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowUtils, EscrowFilter, Status + + print( + EscrowUtils.get_escrows( + EscrowFilter( + networks=[ChainId.POLYGON_AMOY], + status=Status.Pending, + date_from=datetime.datetime(2023, 5, 8), + date_to=datetime.datetime(2023, 6, 8), ) ) + ) + ``` """ from human_protocol_sdk.gql.escrow import get_escrows_query @@ -339,26 +342,33 @@ def get_escrow( escrow_address: str, options: Optional[SubgraphOptions] = None, ) -> Optional[EscrowData]: - """Returns the escrow for a given address. + """Fetch a single escrow by its address. - :param chain_id: Network in which the escrow has been deployed - :param escrow_address: Address of the escrow - :param options: Optional config for subgraph requests + Retrieves detailed information about a specific escrow contract from the subgraph. - :return: Escrow data + Args: + chain_id (ChainId): Network where the escrow has been deployed. + escrow_address (str): Address of the escrow contract. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :example: - .. code-block:: python + Returns: + Escrow data if found, otherwise ``None``. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.escrow import EscrowUtils + Raises: + EscrowClientError: If the chain ID is invalid or the escrow address is malformed. - print( - EscrowUtils.get_escrow( - ChainId.POLYGON_AMOY, - "0x1234567890123456789012345678901234567890" - ) + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowUtils + + print( + EscrowUtils.get_escrow( + ChainId.POLYGON_AMOY, + "0x1234567890123456789012345678901234567890", ) + ) + ``` """ from human_protocol_sdk.gql.escrow import ( get_escrow_query, @@ -424,15 +434,39 @@ def get_status_events( filter: StatusEventFilter, options: Optional[SubgraphOptions] = None, ) -> List[StatusEvent]: - """ - Retrieve status events for specified networks and statuses within a date range. - - :param filter: Object containing all the necessary parameters to filter status events. - :param options: Optional config for subgraph requests - - :return List[StatusEvent]: List of status events matching the query parameters. - - :raise EscrowClientError: If an unsupported chain ID or invalid launcher address is provided. + """Retrieve status change events for escrows. + + Queries the subgraph for escrow status change events within the specified + date range and matching the provided statuses. + + Args: + filter (StatusEventFilter): Filter parameters including chain ID, statuses, + date range, and oracle addresses. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + A list of status change events matching the filter criteria. + Returns an empty list if no matches are found. + + Raises: + EscrowClientError: If an unsupported chain ID or invalid launcher address is provided. + + Example: + ```python + from human_protocol_sdk.constants import ChainId, Status + from human_protocol_sdk.escrow import EscrowUtils + from human_protocol_sdk.filter import StatusEventFilter + import datetime + + events = EscrowUtils.get_status_events( + StatusEventFilter( + chain_id=ChainId.POLYGON_AMOY, + statuses=[Status.Pending, Status.Completed], + date_from=datetime.datetime(2023, 5, 8), + date_to=datetime.datetime(2023, 6, 8), + ) + ) + ``` """ from human_protocol_sdk.gql.escrow import get_status_query @@ -487,15 +521,36 @@ def get_payouts( filter: PayoutFilter, options: Optional[SubgraphOptions] = None, ) -> List[Payout]: - """ - Fetch payouts from the subgraph based on the provided filter. + """Fetch payout records from the subgraph. + + Retrieves payout transactions for escrows based on the provided filter criteria + including escrow address, recipient, and date range. - :param filter: Object containing all the necessary parameters to filter payouts. - :param options: Optional config for subgraph requests + Args: + filter (PayoutFilter): Filter parameters including chain ID, escrow address, + recipient address, date range, pagination, and sorting options. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :return List[Payout]: List of payouts matching the query parameters. + Returns: + A list of payout records matching the query parameters. + Returns an empty list if no matches are found. - :raise EscrowClientError: If an unsupported chain ID or invalid addresses are provided. + Raises: + EscrowClientError: If an unsupported chain ID or invalid addresses are provided. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowUtils + from human_protocol_sdk.filter import PayoutFilter + + payouts = EscrowUtils.get_payouts( + PayoutFilter( + chain_id=ChainId.POLYGON_AMOY, + escrow_address="0x1234567890123456789012345678901234567890", + ) + ) + ``` """ from human_protocol_sdk.gql.payout import get_payouts_query @@ -554,15 +609,36 @@ def get_cancellation_refunds( filter: CancellationRefundFilter, options: Optional[SubgraphOptions] = None, ) -> List[CancellationRefund]: - """ - Fetch cancellation refunds from the subgraph based on the provided filter. + """Fetch cancellation refund events from the subgraph. + + Retrieves cancellation refund transactions for escrows based on the provided + filter criteria including escrow address, receiver, and date range. - :param filter: Object containing all the necessary parameters to filter cancellation refunds. - :param options: Optional config for subgraph requests + Args: + filter (CancellationRefundFilter): Filter parameters including chain ID, + escrow address, receiver address, date range, pagination, and sorting options. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :return List[CancellationRefund]: List of cancellation refunds matching the query parameters. + Returns: + A list of cancellation refunds matching the query parameters. + Returns an empty list if no matches are found. - :raise EscrowClientError: If an unsupported chain ID or invalid addresses are provided. + Raises: + EscrowClientError: If an unsupported chain ID or invalid addresses are provided. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowUtils + from human_protocol_sdk.filter import CancellationRefundFilter + + refunds = EscrowUtils.get_cancellation_refunds( + CancellationRefundFilter( + chain_id=ChainId.POLYGON_AMOY, + escrow_address="0x1234567890123456789012345678901234567890", + ) + ) + ``` """ from human_protocol_sdk.gql.cancel import get_cancellation_refunds_query @@ -624,27 +700,32 @@ def get_cancellation_refund( escrow_address: str, options: Optional[SubgraphOptions] = None, ) -> CancellationRefund: - """ - Returns the cancellation refund for a given escrow address. + """Retrieve the cancellation refund for a specific escrow. - :param chain_id: Network in which the escrow has been deployed - :param escrow_address: Address of the escrow - :param options: Optional config for subgraph requests + Fetches the cancellation refund event associated with a given escrow address. + Each escrow can have at most one cancellation refund. - :return: CancellationRefund data or None + Args: + chain_id (ChainId): Network where the escrow has been deployed. + escrow_address (str): Address of the escrow contract. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :raise EscrowClientError: If an unsupported chain ID or invalid address is provided. + Returns: + Cancellation refund data if found, otherwise ``None``. - :example: - .. code-block:: python + Raises: + EscrowClientError: If an unsupported chain ID or invalid escrow address is provided. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.escrow import EscrowUtils + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.escrow import EscrowUtils - refund = EscrowUtils.get_cancellation_refund( - ChainId.POLYGON_AMOY, - "0x1234567890123456789012345678901234567890" - ) + refund = EscrowUtils.get_cancellation_refund( + ChainId.POLYGON_AMOY, + "0x1234567890123456789012345678901234567890", + ) + ``` """ from human_protocol_sdk.gql.cancel import ( get_cancellation_refund_by_escrow_query, diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/filter.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/filter.py index da3f6b9bff..896bc09fd2 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/filter.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/filter.py @@ -1,5 +1,11 @@ #!/usr/bin/env python3 +"""Filter classes for querying Human Protocol subgraph data. + +This module provides filter classes for various query operations including escrows, +payouts, transactions, statistics, and more. +""" + from datetime import datetime from typing import List, Optional @@ -10,16 +16,27 @@ class FilterError(Exception): - """ - Raises when some error happens when building filter object. - """ + """Exception raised when filter construction or validation fails.""" pass class EscrowFilter: - """ - A class used to filter escrow requests. + """Filter configuration for querying escrows from the subgraph. + + Attributes: + chain_id (ChainId): Network to request data from. + launcher (Optional[str]): Launcher address to filter by. + reputation_oracle (Optional[str]): Reputation oracle address to filter by. + recording_oracle (Optional[str]): Recording oracle address to filter by. + exchange_oracle (Optional[str]): Exchange oracle address to filter by. + job_requester_id (Optional[str]): Job requester identifier to filter by. + status (Optional[Status | List[Status]]): Escrow status or list of statuses to filter by. + date_from (Optional[datetime]): Filter escrows created from this date. + date_to (Optional[datetime]): Filter escrows created until this date. + first (int): Number of items per page (max 1000). + skip (int): Number of items to skip for pagination. + order_direction (OrderDirection): Sort order for results. """ def __init__( @@ -38,20 +55,9 @@ def __init__( order_direction: OrderDirection = OrderDirection.DESC, ): """ - Initializes a EscrowFilter instance. - - :param chain_id: Network to request data - :param launcher: Launcher address - :param reputation_oracle: Reputation oracle address - :param recording_oracle: Recording oracle address - :param exchange_oracle: Exchange oracle address - :param job_requester_id: Job requester id - :param status: Escrow status - :param date_from: Created from date - :param date_to: Created to date - :param first: Number of items per page - :param skip: Page number to retrieve - :param order_direction: Order of results, "asc" or "desc" + Raises: + FilterError: If chain ID is invalid, addresses are malformed, date range is invalid, + or order direction is invalid. """ if chain_id.value not in set(chain_id.value for chain_id in ChainId): @@ -94,8 +100,17 @@ def __init__( class PayoutFilter: - """ - A class used to filter payout requests. + """Filter configuration for querying payout events from the subgraph. + + Attributes: + chain_id (ChainId): Chain where payouts were recorded. + escrow_address (Optional[str]): Escrow address to filter payouts by. + recipient (Optional[str]): Recipient address to filter payouts by. + date_from (Optional[datetime]): Filter payouts from this date. + date_to (Optional[datetime]): Filter payouts until this date. + first (int): Number of items per page. + skip (int): Number of items to skip for pagination. + order_direction (OrderDirection): Sort order for results. """ def __init__( @@ -110,16 +125,8 @@ def __init__( order_direction: OrderDirection = OrderDirection.DESC, ): """ - Initializes a filter for payouts. - - :param chain_id: The chain ID where the payouts are recorded. - :param escrow_address: Optional escrow address to filter payouts. - :param recipient: Optional recipient address to filter payouts. - :param date_from: Optional start date for filtering. - :param date_to: Optional end date for filtering. - :param first: Optional number of payouts per page. Default is 10. - :param skip: Optional number of payouts to skip. Default is 0. - :param order_direction: Optional order direction. Default is DESC. + Raises: + FilterError: If addresses are malformed or date range is invalid. """ if escrow_address and not Web3.is_address(escrow_address): @@ -144,8 +151,22 @@ def __init__( class TransactionFilter: - """ - A class used to filter transactions. + """Filter configuration for querying blockchain transactions from the subgraph. + + Attributes: + chain_id (ChainId): Chain to filter transactions from. + from_address (Optional[str]): Sender address to filter by. + to_address (Optional[str]): Recipient address to filter by. + start_date (Optional[datetime]): Filter transactions from this date. + end_date (Optional[datetime]): Filter transactions until this date. + start_block (Optional[int]): Filter transactions from this block number. + end_block (Optional[int]): Filter transactions until this block number. + method (Optional[str]): Method signature to filter transactions by. + escrow (Optional[str]): Escrow address to filter transactions by. + token (Optional[str]): Token address to filter transactions by. + first (int): Number of items per page (max 1000). + skip (int): Number of items to skip for pagination. + order_direction (OrderDirection): Sort order for results. """ def __init__( @@ -165,23 +186,9 @@ def __init__( order_direction: OrderDirection = OrderDirection.DESC, ): """ - Initializes a TransactionsFilter instance. - - :param chain_id: Chain ID to filter transactions from - :param from_address: Sender address - :param to_address: Receiver address - :param start_date: Start date for filtering transactions - :param end_date: End date for filtering transactions - :param start_block: Start block number for filtering transactions - :param end_block: End block number for filtering transactions - :param method: Method name to filter transactions - :param escrow: Escrow address to filter transactions - :param token: Token address to filter transactions - :param first: Number of items per page - :param skip: Page number to retrieve - :param order: Order of results, "asc" or "desc" - - :raises ValueError: If start_date is after end_date + Raises: + ValueError: If addresses are malformed, date/block ranges are invalid, + or order direction is invalid. """ if from_address and not Web3.is_address(from_address): @@ -231,28 +238,29 @@ def __init__( class StatisticsFilter: - """ - A class used to filter statistical data. - - :param date_from: Start date for the query range. - :param date_to: End date for the query range. - :param first: Number of items per page. - :param skip: Page number to retrieve. - :param order_direction: Order of results, "asc" or "desc". - - :example: - .. code-block:: python - - from datetime import datetime - from human_protocol_sdk.filter import StatisticsFilter - - filter = StatisticsFilter( - date_from=datetime(2023, 1, 1), - date_to=datetime(2023, 12, 31), - first=10, - skip=0, - order_direction=OrderDirection.ASC - ) + """Filter configuration for querying statistical data from the subgraph. + + Attributes: + date_from (Optional[datetime]): Start date for the query range. + date_to (Optional[datetime]): End date for the query range. + first (int): Number of items per page (max 1000). + skip (int): Number of items to skip for pagination. + order_direction (OrderDirection): Sort order for results. + + Example: + ```python + from datetime import datetime + from human_protocol_sdk.filter import StatisticsFilter + from human_protocol_sdk.constants import OrderDirection + + filter = StatisticsFilter( + date_from=datetime(2023, 1, 1), + date_to=datetime(2023, 12, 31), + first=10, + skip=0, + order_direction=OrderDirection.ASC + ) + ``` """ def __init__( @@ -263,6 +271,11 @@ def __init__( skip: int = 0, order_direction: OrderDirection = OrderDirection.ASC, ): + """ + Raises: + FilterError: If date range is invalid or order direction is invalid. + """ + if date_from and date_to and date_from > date_to: raise FilterError( f"Invalid dates: {date_from} must be earlier than {date_to}" @@ -281,6 +294,19 @@ def __init__( class StatusEventFilter: + """Filter configuration for querying escrow status change events. + + Attributes: + chain_id (ChainId): Chain where status events were recorded. + statuses (List[Status]): List of statuses to filter by. + date_from (Optional[datetime]): Filter events from this date. + date_to (Optional[datetime]): Filter events until this date. + launcher (Optional[str]): Launcher address to filter by. + first (int): Number of items per page. + skip (int): Number of items to skip for pagination. + order_direction (OrderDirection): Sort order for results. + """ + def __init__( self, chain_id: ChainId, @@ -322,8 +348,15 @@ def __init__( class WorkerFilter: - """ - A class used to filter workers. + """Filter configuration for querying worker data from the subgraph. + + Attributes: + chain_id (ChainId): Chain to request worker data from. + worker_address (Optional[str]): Worker address to filter by. + order_by (Optional[str]): Property to order results by (e.g., "payoutCount"). + order_direction (OrderDirection): Sort order for results. + first (int): Number of items per page (1-1000). + skip (int): Number of items to skip for pagination. """ def __init__( @@ -336,15 +369,10 @@ def __init__( skip: int = 0, ): """ - Initializes a WorkerFilter instance. - - :param chain_id: Chain ID to request data - :param worker_address: Address to filter by - :param order_by: Property to order by, e.g., "payoutCount" - :param order_direction: Order direction of results, "asc" or "desc" - :param first: Number of items per page - :param skip: Number of items to skip (for pagination) + Raises: + FilterError: If order direction is invalid. """ + if order_direction.value not in set( order_direction.value for order_direction in OrderDirection ): @@ -359,6 +387,24 @@ def __init__( class StakersFilter: + """Filter configuration for querying staker data from the subgraph. + + Attributes: + chain_id (ChainId): Chain to request staker data from. + min_staked_amount (Optional[str]): Minimum staked amount to filter by. + max_staked_amount (Optional[str]): Maximum staked amount to filter by. + min_locked_amount (Optional[str]): Minimum locked amount to filter by. + max_locked_amount (Optional[str]): Maximum locked amount to filter by. + min_withdrawn_amount (Optional[str]): Minimum withdrawn amount to filter by. + max_withdrawn_amount (Optional[str]): Maximum withdrawn amount to filter by. + min_slashed_amount (Optional[str]): Minimum slashed amount to filter by. + max_slashed_amount (Optional[str]): Maximum slashed amount to filter by. + order_by (Optional[str]): Property to order results by (e.g., "lastDepositTimestamp"). + order_direction (OrderDirection): Sort order for results. + first (Optional[int]): Number of items per page. + skip (Optional[int]): Number of items to skip for pagination. + """ + def __init__( self, chain_id: ChainId, @@ -391,8 +437,17 @@ def __init__( class CancellationRefundFilter: - """ - A class used to filter cancellation refunds. + """Filter configuration for querying cancellation refund events. + + Attributes: + chain_id (ChainId): Chain to request refund data from. + escrow_address (Optional[str]): Escrow address to filter by. + receiver (Optional[str]): Receiver address to filter by. + date_from (Optional[datetime]): Filter refunds from this date. + date_to (Optional[datetime]): Filter refunds until this date. + first (int): Number of items per page. + skip (int): Number of items to skip for pagination. + order_direction (OrderDirection): Sort order for results. """ def __init__( @@ -407,16 +462,11 @@ def __init__( order_direction: OrderDirection = OrderDirection.DESC, ): """ - Initializes a CancellationRefundFilter instance. - :param chain_id: Chain ID to request data - :param escrow_address: Address of the escrow to filter by - :param receiver: Address of the receiver to filter by - :param date_from: Start date for filtering - :param date_to: End date for filtering - :param first: Number of items per page - :param skip: Number of items to skip (for pagination) - :param order_direction: Order direction of results, "asc" or "desc" + Raises: + FilterError: If chain ID is invalid, addresses are malformed, + or date range is invalid. """ + if chain_id.value not in set(chain_id.value for chain_id in ChainId): raise FilterError(f"Invalid ChainId") if escrow_address and not Web3.is_address(escrow_address): diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_client.py index db199fc264..d5b4abf33e 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_client.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_client.py @@ -1,23 +1,15 @@ -""" -This client enables performing actions on the KVStore contract and -obtaining information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the web3. -To use this client, you need to create a Web3 instance and configure the default account, -as well as some middlewares. - -Code Example ------------- +"""Client for interacting with the KVStore contract. -* With Signer - -.. code-block:: python +Selects the network based on the Web3 chain id. Configure Web3 with an account +and signer middleware for writes; read operations work without a signer. +Examples: + With signer: + ```python from eth_typing import URI from web3 import Web3 from web3.middleware import SignAndSendRawMiddlewareBuilder from web3.providers.auto import load_provider_from_uri - from human_protocol_sdk.kvstore import KVStoreClient def get_w3_with_priv_key(priv_key: str): @@ -26,29 +18,25 @@ def get_w3_with_priv_key(priv_key: str): w3.eth.default_account = gas_payer.address w3.middleware_onion.inject( SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', + "SignAndSendRawMiddlewareBuilder", layer=0, ) - return (w3, gas_payer) + return w3 - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') + w3 = get_w3_with_priv_key("YOUR_PRIVATE_KEY") kvstore_client = KVStoreClient(w3) + ``` -* Without Signer (For read operations only) - -.. code-block:: python - + Read-only: + ```python from eth_typing import URI from web3 import Web3 from web3.providers.auto import load_provider_from_uri - from human_protocol_sdk.kvstore import KVStoreClient w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) kvstore_client = KVStoreClient(w3) - -Module ------- + ``` """ import logging @@ -71,24 +59,44 @@ def get_w3_with_priv_key(priv_key: str): class KVStoreClientError(Exception): - """ - Raises when some error happens when interacting with kvstore. - """ + """Exception raised when errors occur during KVStore operations.""" pass class KVStoreClient: - """ - A class used to manage kvstore on the HUMAN network. + """Client for interacting with the KVStore smart contract. + + This client provides methods to read and write key-value pairs on-chain, + supporting both individual and bulk operations, as well as URL storage with + content hash verification. + + Attributes: + w3 (Web3): Web3 instance configured for the target network. + network (dict): Network configuration for the current chain. + kvstore_contract (Contract): Contract instance for the KVStore. + gas_limit (Optional[int]): Optional gas limit for transactions. """ def __init__(self, web3: Web3, gas_limit: Optional[int] = None): - """ - Initializes a KVStore instance. + """Initialize a KVStoreClient instance. - :param web3: The Web3 object - :param gas_limit: (Optional) Gas limit for transactions + Args: + web3 (Web3): Web3 instance configured for the target network. + Must have a valid provider and chain ID. + gas_limit (Optional[int]): Optional gas limit for transactions. + + Raises: + KVStoreClientError: If chain ID is invalid or network configuration is missing. + + Example: + ```python + from web3 import Web3 + from human_protocol_sdk.kvstore import KVStoreClient + + w3 = Web3(Web3.HTTPProvider("http://localhost:8545")) + kvstore_client = KVStoreClient(w3) + ``` """ # Initialize web3 instance @@ -118,39 +126,25 @@ def __init__(self, web3: Web3, gas_limit: Optional[int] = None): @requires_signer def set(self, key: str, value: str, tx_options: Optional[TxParams] = None) -> None: - """ - Sets the value of a key-value pair in the contract. - - :param key: The key of the key-value pair to set - :param value: The value of the key-value pair to set - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.kvstore import KVStoreClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - kvstore_client = KVStoreClient(w3) - kvstore_client.set('Role', 'RecordingOracle') + """Set a key-value pair in the KVStore contract. + + Stores a single key-value pair on-chain associated with the sender's address. + + Args: + key (str): Key to set (cannot be empty). + value (str): Value to assign to the key. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + None + + Raises: + KVStoreClientError: If the key is empty or the transaction fails. + + Example: + ```python + kvstore_client.set("Role", "RecordingOracle") + ``` """ if not key: @@ -168,42 +162,30 @@ def get_w3_with_priv_key(priv_key: str): def set_bulk( self, keys: List[str], values: List[str], tx_options: Optional[TxParams] = None ) -> None: - """ - Sets multiple key-value pairs in the contract. - - :param keys: A list of keys to set - :param values: A list of values to set - :param tx_options: (Optional) Additional transaction parameters - - :return: None + """Set multiple key-value pairs in the KVStore contract. - :example: - .. code-block:: python + Stores multiple key-value pairs on-chain in a single transaction, + all associated with the sender's address. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Args: + keys (List[str]): List of keys to set (no key can be empty). + values (List[str]): Corresponding list of values (must match keys length). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - from human_protocol_sdk.kvstore import KVStoreClient + Returns: + None - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) + Raises: + KVStoreClientError: If any key is empty, arrays are empty, arrays have different + lengths, or the transaction fails. - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - kvstore_client = KVStoreClient(w3) - - keys = ['Role', 'Webhook_url'] - values = ['RecordingOracle', 'http://localhost'] - kvstore_client.set_bulk(keys, values) + Example: + ```python + kvstore_client.set_bulk( + ["Role", "Webhook_url"], + ["RecordingOracle", "http://localhost"], + ) + ``` """ if "" in keys: @@ -228,43 +210,31 @@ def set_file_url_and_hash( key: Optional[str] = "url", tx_options: Optional[TxParams] = None, ) -> None: - """ - Sets a URL value for the address that submits the transaction, and its hash. - - :param url: URL to set - :param key: Configurable URL key. `url` by default. - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :raise KVStoreClientError: If an error occurs while validating URL, or handling transaction - - :example: - .. code-block:: python + """Set a URL value and its content hash in the KVStore. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Fetches the content from the URL, computes its hash, and stores both + the URL and hash on-chain. The hash key is automatically generated + by appending ``_hash`` to the provided key. - from human_protocol_sdk.kvstore import KVStoreClient + Args: + url (str): URL to store (must be valid and accessible). + key (Optional[str]): Configurable URL key. Defaults to ``"url"``. + The hash will be stored with key ``"{key}_hash"``. + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) + Returns: + None - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - kvstore_client = KVStoreClient(w3) + Raises: + KVStoreClientError: If the URL is invalid, unreachable, or the transaction fails. - kvstore_client.set_file_url_and_hash('http://localhost') - kvstore_client.set_file_url_and_hash('https://linkedin.com/me', 'linkedin_url') + Example: + ```python + kvstore_client.set_file_url_and_hash("http://localhost/manifest.json") + kvstore_client.set_file_url_and_hash( + "https://linkedin.com/me", "linkedin_url" + ) + ``` """ if not validate_url(url): raise KVStoreClientError(f"Invalid URL: {url}") @@ -280,24 +250,28 @@ def get_w3_with_priv_key(priv_key: str): handle_error(e, KVStoreClientError) def get(self, address: str, key: str) -> str: - """ - Gets the value of a key-value pair in the contract. - :param address: The Ethereum address associated with the key-value pair - :param key: The key of the key-value pair to get + """Get the value of a key-value pair from the KVStore. - :return: The value of the key-value pair if it exists + Retrieves the value associated with a key for a specific address. - :example: - .. code-block:: python + Args: + address (str): Ethereum address associated with the key-value pair. + key (str): Key to retrieve (cannot be empty). - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - from human_protocol_sdk.kvstore import KVStoreClient + Returns: + Value of the key-value pair if it exists, empty string otherwise. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - kvstore_client = KVStoreClient(w3) - role = kvstore_client.get('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'Role') + Raises: + KVStoreClientError: If the key is empty, address is invalid, or the query fails. + + Example: + ```python + role = kvstore_client.get( + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + "Role", + ) + print(role) # "RecordingOracle" + ``` """ if not key: diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_utils.py index fdb371ddf2..2672136569 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_utils.py @@ -1,23 +1,17 @@ -""" -Utility class for KVStore-related operations. - -Code Example ------------- - -.. code-block:: python +"""Utility helpers for KVStore queries. +Example: + ```python from human_protocol_sdk.constants import ChainId from human_protocol_sdk.kvstore import KVStoreUtils print( KVStoreUtils.get_kvstore_data( ChainId.POLYGON_AMOY, - "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65" + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", ) ) - -Module ------- + ``` """ from datetime import datetime @@ -37,20 +31,24 @@ class KVStoreData: - def __init__(self, key: str, value: str): - """ - Initializes a KVStoreData instance. + """Represents a key-value pair from the KVStore. - :param key: Key - :param value: Value - """ + Attributes: + key (str): The key of the key-value pair. + value (str): The value associated with the key. + """ + + def __init__(self, key: str, value: str): self.key = key self.value = value class KVStoreUtils: - """ - A utility class that provides additional KVStore-related functionalities. + """Utility class providing KVStore-related query and data retrieval functions. + + This class offers static methods to fetch KVStore data from the HUMAN Protocol + subgraph, including individual key-value pairs, bulk data, and specialized + methods for URLs with hash verification and public keys. """ @staticmethod @@ -59,26 +57,34 @@ def get_kvstore_data( address: str, options: Optional[SubgraphOptions] = None, ) -> Optional[List[KVStoreData]]: - """Returns the KVStore data for a given address. - - :param chain_id: Network in which the KVStore data has been deployed - :param address: Address of the KVStore - :param options: Optional config for subgraph requests - - :return: List of KVStore data - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.kvstore import KVStoreUtils - - print( - KVStoreUtils.get_kvstore_data( - ChainId.POLYGON_AMOY, - "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65" - ) - ) + """Retrieve all KVStore data for a given address. + + Queries the subgraph for all key-value pairs associated with a specific address. + + Args: + chain_id (ChainId): Network where the KVStore data has been stored. + address (str): Address whose KVStore data to retrieve. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests + such as custom endpoints or timeout settings. + + Returns: + List of KVStore data entries if found, empty list otherwise. + + Raises: + KVStoreClientError: If the chain ID is invalid or the address is malformed. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.kvstore import KVStoreUtils + + data = KVStoreUtils.get_kvstore_data( + ChainId.POLYGON_AMOY, + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", + ) + for item in data: + print(f"{item.key}: {item.value}") + ``` """ from human_protocol_sdk.gql.kvstore import get_kvstore_by_address_query @@ -120,27 +126,35 @@ def get( key: str, options: Optional[SubgraphOptions] = None, ) -> str: - """Gets the value of a key-value pair in the contract. - - :param chain_id: Network in which the KVStore data has been deployed - :param address: The Ethereum address associated with the key-value pair - :param key: The key of the key-value pair to get - :param options: Optional config for subgraph requests - - :return: The value of the key-value pair if it exists - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.kvstore import KVStoreUtils - - chain_id = ChainId.POLYGON_AMOY - address = '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - key = 'role' - - result = KVStoreUtils.get(chain_id, address, key) - print(result) + """Get the value of a specific key for an address. + + Queries the subgraph for a specific key-value pair associated with an address. + + Args: + chain_id (ChainId): Network where the KVStore data has been stored. + address (str): Ethereum address associated with the key-value pair. + key (str): Key to retrieve (cannot be empty). + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + Value for the key if it exists. + + Raises: + KVStoreClientError: If the key is empty, address is invalid, chain ID is invalid, + or the key is not found for the address. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.kvstore import KVStoreUtils + + role = KVStoreUtils.get( + ChainId.POLYGON_AMOY, + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + "role", + ) + print(role) + ``` """ from human_protocol_sdk.gql.kvstore import get_kvstore_by_address_and_key_query @@ -178,26 +192,40 @@ def get_file_url_and_verify_hash( key: Optional[str] = "url", options: Optional[SubgraphOptions] = None, ) -> str: - """Gets the URL value of the given entity, and verify its hash. - - :param chain_id: Network in which the KVStore data has been deployed - :param address: Address from which to get the URL value. - :param key: Configurable URL key. `url` by default. - :param options: Optional config for subgraph requests - - :return url: The URL value of the given address if exists, and the content is valid - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.kvstore import KVStoreUtils - - chain_id = ChainId.POLYGON_AMOY - address = '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - - url = KVStoreUtils.get_file_url_and_verify_hash(chain_id, address) - linkedin_url = KVStoreUtils.get_file_url_and_verify_hash(chain_id, address, 'linkedin_url') + """Get a stored URL and verify its content hash. + + Retrieves a URL from KVStore, fetches its content, and verifies that the + content hash matches the stored hash value. This ensures the file content + has not been tampered with. + + Args: + chain_id (ChainId): Network where the KVStore data has been stored. + address (str): Address from which to get the URL value. + key (Optional[str]): Configurable URL key. Defaults to ``"url"``. + The hash key is expected to be ``"{key}_hash"``. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + URL value if it exists and the content hash matches. + Returns empty string if URL is not set. + + Raises: + KVStoreClientError: If the address is invalid, hash verification fails, + or the URL is unreachable. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.kvstore import KVStoreUtils + + chain_id = ChainId.POLYGON_AMOY + address = "0x62dD51230A30401C455c8398d06F85e4EaB6309f" + + url = KVStoreUtils.get_file_url_and_verify_hash(chain_id, address) + linkedin_url = KVStoreUtils.get_file_url_and_verify_hash( + chain_id, address, "linkedin_url" + ) + ``` """ if not Web3.is_address(address): @@ -222,23 +250,34 @@ def get_file_url_and_verify_hash( @staticmethod def get_public_key(chain_id: ChainId, address: str) -> str: - """Gets the public key of the given entity, and verify its hash. - - :param chain_id: Network in which the KVStore data has been deployed - :param address: Address from which to get the public key. - - :return public_key: The public key of the given address if exists, and the content is valid - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.kvstore import KVStoreUtils - - chain_id = ChainId.POLYGON_AMOY - address = '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - - public_key = KVStoreUtils.get_public_key(chain_id, address) + """Get the public key of an entity from KVStore. + + Retrieves and validates the public key stored for a given address. + The public key URL is fetched from the ``public_key`` key and verified + against its hash. + + Args: + chain_id (ChainId): Network where the KVStore data has been stored. + address (str): Address from which to get the public key. + + Returns: + Public key content if it exists and is valid. + Returns empty string if no public key is set. + + Raises: + KVStoreClientError: If the address is invalid or hash verification fails. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.kvstore import KVStoreUtils + + public_key = KVStoreUtils.get_public_key( + ChainId.POLYGON_AMOY, + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + ) + print(public_key) + ``` """ public_key_url = KVStoreUtils.get_file_url_and_verify_hash( diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/legacy_encryption.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/legacy_encryption.py index 5ce0f7c801..134fc19d66 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/legacy_encryption.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/legacy_encryption.py @@ -1,12 +1,31 @@ """ -Legacy version of encryption module. -Learn more about [encryption](human_protocol_sdk.encryption.md#human_protocol_sdk.encryption.Encryption). +Legacy encryption utilities for backward compatibility. + +This module provides deprecated encryption functionality maintained for backward +compatibility with older versions of the SDK. For new implementations, use the +``human_protocol_sdk.encryption`` module instead. + +Warning: + This module is deprecated and will be removed in a future version. + Please migrate to ``human_protocol_sdk.encryption.Encryption`` and + ``human_protocol_sdk.encryption.EncryptionUtils``. + +Example: + ```python + # Deprecated - for backward compatibility only + from human_protocol_sdk.legacy_encryption import LegacyEncryption + + # Recommended - use this instead + from human_protocol_sdk.encryption import Encryption + ``` """ +import warnings import hashlib import os import struct import typing as t +from typing import Optional, List, Union from cryptography.hazmat.primitives import hashes, hmac from cryptography.hazmat.primitives.asymmetric import ec @@ -19,65 +38,60 @@ keys as eth_keys, ) from eth_utils import int_to_big_endian +from pgpy import PGPKey, PGPMessage +from pgpy.constants import SymmetricKeyAlgorithm +from pgpy.errors import PGPError class InvalidPublicKey(Exception): - """ - A custom exception raised when trying to convert bytes - into an elliptic curve public key. - """ + """Exception raised when converting bytes into an elliptic curve public key fails.""" pass class DecryptionError(Exception): - """ - Raised when a message could not be decrypted. - """ + """Exception raised when a message could not be decrypted.""" pass class Encryption: - """ - Encryption class specialized in encrypting and decrypting a byte string. + """Encryption class specialized in encrypting and decrypting byte strings using ECIES. + + This class implements Elliptic Curve Integrated Encryption Scheme (ECIES) using + SECP256K1 elliptic curve, AES256 cipher, and HMAC-SHA-256-32. + + Attributes: + ELLIPTIC_CURVE (ec.EllipticCurve): SECP256K1 elliptic curve definition. + KEY_LEN (int): Key length for ECIES (32 bytes for AES256 and HMAC-SHA-256-32). + CIPHER: AES cipher algorithm definition. + MODE: CTR cipher mode definition. + PUBLIC_KEY_LEN (int): Length of public keys in uncompressed form (64 bytes). """ ELLIPTIC_CURVE: ec.EllipticCurve = ec.SECP256K1() - """ Elliptic curve definition. """ - KEY_LEN = 32 - """ ECIES using AES256 and HMAC-SHA-256-32 """ - CIPHER = AES - """ Cipher algorithm definition. """ - MODE = CTR - """ Cipher mode definition. """ - PUBLIC_KEY_LEN: int = 64 - """ - Length of public keys: 512 bit keys in uncompressed form, without - format byte - """ @staticmethod def is_encrypted(data: bytes) -> bool: - """ - Checks whether data is already encrypted by verifying ecies header. - - :param data: Data to be checked. + """Check whether data is already encrypted by verifying ECIES header. - :return: True if data is encrypted, False otherwise. + Args: + data (bytes): Data to be checked for encryption. - :example: - .. code-block:: python + Returns: + ``True`` if data has valid ECIES header (starts with 0x04), ``False`` otherwise. - from human_protocol_sdk.legacy_encryption import Encryption + Example: + ```python + from human_protocol_sdk.legacy_encryption import Encryption - encrypted_message_str = "0402f48d28d29ae3d681e4cbbe499be0803c2a9d94534d0a4501ab79fd531183fbd837a021c1c117f47737e71c430b9d33915615f68c8dcb5e2f4e4dda4c9415d20a8b5fad9770b14067f2dd31a141a8a8da1f56eb2577715409dbf3c39b9bfa7b90c1acd838fe147c95f0e1ca9359a4cfd52367a73a6d6c548b492faa" - - is_encrypted = Encryption.is_encrypted(bytes.fromhex(encrypted_message_str)) + encrypted_hex = "0402f48d28d29ae3d681e4cbbe499be0803c2a9d94534d0a4501ab79fd531183fbd837a021c1c117f47737e71c430b9d33915615f68c8dcb5e2f4e4dda4c9415d20a8b5fad9770b14067f2dd31a141a8a8da1f56eb2577715409dbf3c39b9bfa7b90c1acd838fe147c95f0e1ca9359a4cfd52367a73a6d6c548b492faa" + is_encrypted = Encryption.is_encrypted(bytes.fromhex(encrypted_hex)) + ``` """ return data[:1] == b"\x04" @@ -87,31 +101,39 @@ def encrypt( public_key: eth_datatypes.PublicKey, shared_mac_data: bytes = b"", ) -> bytes: - """ - Encrypt data with ECIES method to the given public key - 1) generate r = random value - 2) generate shared-secret = kdf( ecdhAgree(r, P) ) - 3) generate R = rG [same op as generating a public key] - 4) 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag - - :param data: Data to be encrypted - :param public_key: Public to be used to encrypt provided data. - :param shared_mac_data: shared mac additional data as suffix. - - :return: Encrypted byte string - - :example: - .. code-block:: python - - from human_protocol_sdk.legacy_encryption import Encryption - from eth_keys import datatypes - - public_key_str = "0a1d228684bc8c8c7611df3264f04ebd823651acc46b28b3574d2e69900d5e34f04a26cf13237fa42ab23245b58060c239b356b0a276f57e8de1234c7100fcf9" - - public_key = datatypes.PublicKey(bytes.fromhex(private_key_str)) - - encryption = Encryption() - encrypted_message = encryption.encrypt(b'your message', public_key) + """Encrypt data using ECIES method with the given public key. + + The encryption process follows these steps: + 1. Generate random ephemeral private key r + 2. Generate shared secret using ECDH key agreement + 3. Derive encryption and MAC keys from shared secret + 4. Generate ephemeral public key R = r*G + 5. Encrypt data using AES256-CTR + 6. Generate authentication tag using HMAC-SHA256 + 7. Return: 0x04 || R || IV || ciphertext || tag + + Args: + data (bytes): Data to be encrypted. + public_key (eth_datatypes.PublicKey): Public key to encrypt data for. + shared_mac_data (bytes): Additional data to include in MAC computation. Defaults to empty bytes. + + Returns: + Encrypted message in ECIES format. + + Raises: + DecryptionError: If key exchange fails or public key is invalid. + + Example: + ```python + from human_protocol_sdk.legacy_encryption import Encryption + from eth_keys import datatypes + + public_key_hex = "0a1d228684bc8c8c7611df3264f04ebd823651acc46b28b3574d2e69900d5e34f04a26cf13237fa42ab23245b58060c239b356b0a276f57e8de1234c7100fcf9" + public_key = datatypes.PublicKey(bytes.fromhex(public_key_hex)) + + encryption = Encryption() + encrypted = encryption.encrypt(b'your message', public_key) + ``` """ # 1) generate r = random value @@ -156,33 +178,39 @@ def decrypt( private_key: eth_datatypes.PrivateKey, shared_mac_data: bytes = b"", ) -> bytes: - """ - Decrypt data with ECIES method using the given private key - 1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) ) - 2) verify tag - 3) decrypt - ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R) - [where R = r*G, and recipientPublic = recipientPrivate*G] - - :param data: Data to be decrypted - :param private_key: Private key to be used in agreement. - :param shared_mac_data: shared mac additional data as suffix. - - :return: Decrypted byte string - - :example: - .. code-block:: python - - from human_protocol_sdk.legacy_encryption import Encryption - from eth_keys import datatypes - - private_key_str = "9822f95dd945e373300f8c8459a831846eda97f314689e01f7cf5b8f1c2298b3" - encrypted_message_str = "0402f48d28d29ae3d681e4cbbe499be0803c2a9d94534d0a4501ab79fd531183fbd837a021c1c117f47737e71c430b9d33915615f68c8dcb5e2f4e4dda4c9415d20a8b5fad9770b14067f2dd31a141a8a8da1f56eb2577715409dbf3c39b9bfa7b90c1acd838fe147c95f0e1ca9359a4cfd52367a73a6d6c548b492faa" - - private_key = datatypes.PrivateKey(bytes.fromhex(private_key_str)) - - encryption = Encryption() - encrypted_message = encryption.decrypt(bytes.fromhex(encrypted_message_str), private_key) + """Decrypt data using ECIES method with the given private key. + + The decryption process follows these steps: + 1. Extract ephemeral public key R from message + 2. Generate shared secret using ECDH: ecdhAgree(privateKey, R) + 3. Derive encryption and MAC keys from shared secret + 4. Verify authentication tag + 5. Decrypt ciphertext using AES256-CTR + + Args: + data (bytes): Encrypted message in ECIES format. + private_key (eth_datatypes.PrivateKey): Private key to decrypt the data. + shared_mac_data (bytes): Additional data used in MAC computation. Defaults to empty bytes. + + Returns: + Decrypted plaintext data. + + Raises: + DecryptionError: If ECIES header is invalid, tag verification fails, + key exchange fails, or decryption fails. + + Example: + ```python + from human_protocol_sdk.legacy_encryption import Encryption + from eth_keys import datatypes + + private_key_hex = "9822f95dd945e373300f8c8459a831846eda97f314689e01f7cf5b8f1c2298b3" + encrypted_hex = "0402f48d28d29ae3d681e4cbbe499be0803c2a9d94534d0a4501ab79fd531183fbd837a021c1c117f47737e71c430b9d33915615f68c8dcb5e2f4e4dda4c9415d20a8b5fad9770b14067f2dd31a141a8a8da1f56eb2577715409dbf3c39b9bfa7b90c1acd838fe147c95f0e1ca9359a4cfd52367a73a6d6c548b492faa" + + private_key = datatypes.PrivateKey(bytes.fromhex(private_key_hex)) + encryption = Encryption() + decrypted = encryption.decrypt(bytes.fromhex(encrypted_hex), private_key) + ``` """ if self.is_encrypted(data) is False: @@ -232,26 +260,20 @@ def decrypt( def _process_key_exchange( self, private_key: eth_datatypes.PrivateKey, public_key: eth_datatypes.PublicKey ) -> bytes: - """ - Performs a key exchange operation using the - ECDH (Elliptic-curve Diffie–Hellman) algorithm. + """Perform ECDH key exchange operation. - NIST SP 800-56a Concatenation Key Derivation Function - (see section 4) - Key agreement. - https://csrc.nist.gov/CSRC/media/Publications/sp/800-56a/archive/2006-05-03/documents/sp800-56-draft-jul2005.pdf + Implements NIST SP 800-56a Concatenation Key Derivation Function (section 4) + for key agreement using ECDH (Elliptic-curve Diffie-Hellman) algorithm. + Args: + private_key (eth_datatypes.PrivateKey): Private key for the initiator. + public_key (eth_datatypes.PublicKey): Public key for the responder. - A key establishment procedure where the resultant secret keying - material is a function of information contributed by two participants, - so that no party can predetermine the value of the secret keying - material independently from the contribut ions of the other parties. - Contrast with key transport. + Returns: + Shared secret key material resulting from the ECDH exchange. - :param private_key: Private key to be used in agreement (the initiator). - :param public_key: Public key to be exchanged (responder). - - :return: Key material resulted of the exchange between two keys, assuming - that they derive the same key material + Raises: + InvalidPublicKey: If the public key cannot be converted to a valid elliptic curve point. """ private_key_int = int(t.cast(int, private_key)) @@ -275,18 +297,18 @@ def _process_key_exchange( raise InvalidPublicKey(str(error)) from error def generate_private_key(self) -> eth_datatypes.PrivateKey: - """ - Generates a new SECP256K1 private key and return it - - :return: New SECP256K1 private key. + """Generate a new SECP256K1 private key. - :example: - .. code-block:: python + Returns: + Newly generated SECP256K1 private key. - from human_protocol_sdk.legacy_encryption import Encryption + Example: + ```python + from human_protocol_sdk.legacy_encryption import Encryption - encryption = Encryption() - private_key = encryption.generate_private_key() + encryption = Encryption() + private_key = encryption.generate_private_key() + ``` """ key = ec.generate_private_key(curve=self.ELLIPTIC_CURVE) @@ -296,41 +318,37 @@ def generate_private_key(self) -> eth_datatypes.PrivateKey: @staticmethod def generate_public_key(private_key: bytes) -> eth_keys.PublicKey: - """ - Generates a public key with combination to private key provided. - - :param private_key: Private to be used to create public key. - - :return: Public key object. + """Generate a public key from the given private key. - :example: - .. code-block:: python + Args: + private_key (bytes): Private key bytes to derive the public key from. - from human_protocol_sdk.legacy_encryption import Encryption + Returns: + Public key object corresponding to the private key. - private_key_str = "9822f95dd945e373300f8c8459a831846eda97f314689e01f7cf5b8f1c2298b3" + Example: + ```python + from human_protocol_sdk.legacy_encryption import Encryption - public_key = Encryption.generate_public_key(bytes.fromhex(private_key_str)) + private_key_hex = "9822f95dd945e373300f8c8459a831846eda97f314689e01f7cf5b8f1c2298b3" + public_key = Encryption.generate_public_key(bytes.fromhex(private_key_hex)) + ``` """ private_key_obj = eth_keys.PrivateKey(private_key) return private_key_obj.public_key def _get_key_derivation(self, key_material: bytes) -> bytes: - """ - NIST SP 800-56a Concatenation Key Derivation Function - (see section 5.8.1) - KDF. - - An Approved key derivation function (KDF) shall be used to derive - secret keying material from a shared secret. + """Derive encryption and MAC keys from shared secret using KDF. - Pretty much copied from geth's implementation: - https://github.com/ethereum/go-ethereum/blob/673007d7aed1d2678ea3277eceb7b55dc29cf092/crypto/ecies/ecies.go#L167 + Implements NIST SP 800-56a Concatenation Key Derivation Function (section 5.8.1). + Uses SHA256 hash to derive secret keying material from ECDH shared secret. - :param key_material: Key material derived from ECDH (shared secret) exchange and - must be processed to deverive a key secret. + Args: + key_material (bytes): Shared secret from ECDH key exchange. - :return: Key secret derived - a called KDF + Returns: + Derived key secret (concatenation of encryption key and MAC key). """ key = b"" @@ -350,7 +368,15 @@ def _get_key_derivation(self, key_material: bytes) -> bytes: @staticmethod def _hmac_sha256(key: bytes, msg: bytes) -> bytes: - """Generates hash MAC using SHA256 Hash Algorithm""" + """Generate HMAC using SHA256 hash algorithm. + + Args: + key (bytes): HMAC key. + msg (bytes): Message to authenticate. + + Returns: + HMAC-SHA256 digest. + """ mac = hmac.HMAC(key, hashes.SHA256()) mac.update(msg) @@ -358,10 +384,11 @@ def _hmac_sha256(key: bytes, msg: bytes) -> bytes: @staticmethod def _pad32(value: bytes) -> bytes: - """ - :param value: Value to be add padding on the data. + """Pad value to 32 bytes with leading zeros. - :return: value with added code added. - """ + Args: + value (bytes): Value to pad. - return value.rjust(32, b"\x00") + Returns: + Value padded to 32 bytes. + """ diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py index c4332ea4fb..ed467d0389 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/operator/operator_utils.py @@ -1,11 +1,7 @@ -""" -Utility class for operator-related operations. - -Code Example ------------- - -.. code-block:: python +"""Utility helpers for operator-related queries. +Example: + ```python from human_protocol_sdk.constants import ChainId from human_protocol_sdk.operator import OperatorUtils, OperatorFilter @@ -14,9 +10,7 @@ OperatorFilter(chain_id=ChainId.POLYGON_AMOY, roles=["Job Launcher"]) ) ) - -Module ------- + ``` """ import logging @@ -32,16 +26,22 @@ class OperatorUtilsError(Exception): - """ - Raised when an error occurs while interacting with the operator. - """ + """Exception raised when errors occur during operator operations.""" pass class OperatorFilter: - """ - A class used to filter operators. + """Filter configuration for querying operators from the subgraph. + + Attributes: + chain_id (ChainId): Chain ID to request data from. + roles (List[str]): List of roles to filter by. + min_staked_amount (Optional[int]): Minimum staked amount to include operators. + order_by (Optional[str]): Property to order results by (e.g., "role", "stakedAmount"). + order_direction (OrderDirection): Order direction (ascending or descending). + first (int): Number of items per page (1-1000). + skip (int): Number of items to skip for pagination. """ def __init__( @@ -54,16 +54,19 @@ def __init__( first: int = 10, skip: int = 0, ): - """ - Initializes a OperatorFilter instance. - - :param chain_id: Chain ID to request data - :param roles: Roles to filter by - :param min_staked_amount: Minimum amount staked to filter by - :param order_by: Property to order by, e.g., "role" - :param order_direction: Order direction of results, "asc" or "desc" - :param first: Number of items per page - :param skip: Number of items to skip (for pagination) + """Configure filtering options for operator queries. + + Args: + chain_id: Chain ID to request data. + roles: Roles to filter by. + min_staked_amount: Minimum amount staked to include. + order_by: Property to order by, e.g., "role". + order_direction: Order direction of results. + first: Number of items per page. + skip: Number of items to skip (for pagination). + + Raises: + OperatorUtilsError: If chain ID or order direction is invalid. """ if chain_id not in ChainId: @@ -84,6 +87,32 @@ def __init__( class OperatorData: + """Represents operator information retrieved from the subgraph. + + Attributes: + chain_id (ChainId): Chain where the operator is registered. + id (str): Unique operator identifier. + address (str): Operator's Ethereum address. + staked_amount (Optional[int]): Amount staked by the operator. + locked_amount (Optional[int]): Amount currently locked. + locked_until_timestamp (Optional[int]): Time in milliseconds until locked amount is released. + withdrawn_amount (Optional[int]): Total amount withdrawn. + slashed_amount (Optional[int]): Total amount slashed. + amount_jobs_processed (int): Number of jobs launched/processed by the operator. + role (Optional[str]): Current role of the operator (e.g., "Job Launcher", "Recording Oracle"). + fee (Optional[int]): Operator fee percentage. + public_key (Optional[str]): Operator's public key. + webhook_url (Optional[str]): Webhook URL for notifications. + website (Optional[str]): Operator's website URL. + url (Optional[str]): Operator URL. + job_types (List[str]): List of supported job types. + registration_needed (Optional[bool]): Whether registration is required. + registration_instructions (Optional[str]): Instructions for registration. + reputation_networks (List[str]): List of reputation network addresses. + name (Optional[str]): Operator name. + category (Optional[str]): Operator category. + """ + def __init__( self, chain_id: ChainId, @@ -108,30 +137,30 @@ def __init__( name: Optional[str] = None, category: Optional[str] = None, ): - """ - Initializes a OperatorData instance. - - :param chain_id: Chain Identifier - :param id: Identifier - :param address: Address - :param staked_amount: Amount staked - :param locked_amount: Amount locked - :param locked_until_timestamp: Locked until timestamp - :param withdrawn_amount: Amount withdrawn - :param slashed_amount: Amount slashed - :param amount_jobs_processed: Amount of jobs launched - :param role: Role - :param fee: Fee - :param public_key: Public key - :param webhook_url: Webhook URL - :param website: Website URL - :param url: URL - :param job_types: Job types - :param registration_needed: Whether registration is needed - :param registration_instructions: Registration instructions - :param reputation_networks: List of reputation networks - :param name: Name - :param category: Category + """Represents operator information returned from the subgraph. + + Args: + chain_id: Chain identifier. + id: Operator ID. + address: Operator address. + amount_jobs_processed: Jobs launched by the operator. + reputation_networks: List of reputation networks. + staked_amount: Amount staked. + locked_amount: Amount locked. + locked_until_timestamp: Time (in seconds) until locked amount is released. + withdrawn_amount: Amount withdrawn. + slashed_amount: Amount slashed. + role: Current role of the operator. + fee: Operator fee. + public_key: Public key. + webhook_url: Webhook URL. + website: Website URL. + url: Operator URL. + job_types: Supported job types. + registration_needed: Whether registration is needed. + registration_instructions: Registration instructions. + name: Operator name. + category: Operator category. """ self.chain_id = chain_id @@ -176,25 +205,28 @@ def __init__( class RewardData: + """Represents a reward distributed to a slasher. + + Attributes: + escrow_address (str): Address of the escrow that generated the reward. + amount (int): Reward amount in token's smallest unit. + """ + def __init__( self, escrow_address: str, amount: int, ): - """ - Initializes a RewardData instance. - - :param escrow_address: Escrow address - :param amount: Amount - """ - self.escrow_address = escrow_address self.amount = amount class OperatorUtils: - """ - A utility class that provides additional operator-related functionalities. + """Utility class providing operator-related query and data retrieval functions. + + This class offers static methods to fetch operator data, including filtered + operator lists, individual operator details, reputation network operators, + and reward information from the Human Protocol subgraph. """ @staticmethod @@ -202,24 +234,32 @@ def get_operators( filter: OperatorFilter, options: Optional[SubgraphOptions] = None, ) -> List[OperatorData]: - """Get operators data of the protocol. + """Retrieve a list of operators matching the provided filter criteria. - :param filter: Operator filter - :param options: Optional config for subgraph requests + Queries the subgraph for operators that match the specified parameters + including roles, minimum staked amount, and ordering preferences. - :return: List of operators data + Args: + filter (OperatorFilter): Filter parameters including chain ID, roles, + minimum staked amount, ordering, and pagination options. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests + such as custom endpoints or timeout settings. - :example: - .. code-block:: python + Returns: + A list of operator records matching the filter criteria. + Returns an empty list if no matches are found. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils, OperatorFilter + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.operator import OperatorUtils, OperatorFilter - print( - OperatorUtils.get_operators( - OperatorFilter(chain_id=ChainId.POLYGON_AMOY, roles=["Job Launcher"]) - ) - ) + operators = OperatorUtils.get_operators( + OperatorFilter(chain_id=ChainId.POLYGON_AMOY, roles=["Job Launcher"]) + ) + for operator in operators: + print(f"{operator.address}: {operator.role}") + ``` """ from human_protocol_sdk.gql.operator import get_operators_query @@ -290,25 +330,34 @@ def get_operator( operator_address: str, options: Optional[SubgraphOptions] = None, ) -> Optional[OperatorData]: - """Gets the operator details. + """Retrieve a single operator by their address. - :param chain_id: Network in which the operator exists - :param operator_address: Address of the operator - :param options: Optional config for subgraph requests + Fetches detailed information about a specific operator from the subgraph. - :return: Operator data if exists, otherwise None + Args: + chain_id (ChainId): Network where the operator is registered. + operator_address (str): Ethereum address of the operator. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :example: - .. code-block:: python + Returns: + Operator data if found, otherwise ``None``. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils + Raises: + OperatorUtilsError: If the chain ID is invalid or the operator address is malformed. - chain_id = ChainId.POLYGON_AMOY - operator_address = '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.operator import OperatorUtils - operator_data = OperatorUtils.get_operator(chain_id, operator_address) - print(operator_data) + chain_id = ChainId.POLYGON_AMOY + operator_address = "0x62dD51230A30401C455c8398d06F85e4EaB6309f" + + operator_data = OperatorUtils.get_operator(chain_id, operator_address) + if operator_data: + print(f"Role: {operator_data.role}") + print(f"Staked: {operator_data.staked_amount}") + ``` """ from human_protocol_sdk.gql.operator import get_operator_query @@ -369,26 +418,36 @@ def get_reputation_network_operators( role: Optional[str] = None, options: Optional[SubgraphOptions] = None, ) -> List[OperatorData]: - """Get the reputation network operators of the specified address. + """Retrieve operators registered under a specific reputation network. - :param chain_id: Network in which the reputation network exists - :param address: Address of the reputation oracle - :param role: (Optional) Role of the operator - :param options: Optional config for subgraph requests + Fetches all operators associated with a reputation oracle, optionally + filtered by role. - :return: Returns an array of operator details + Args: + chain_id (ChainId): Network where the reputation network exists. + address (str): Ethereum address of the reputation oracle. + role (Optional[str]): Optional role to filter operators (e.g., "Job Launcher"). + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :example: - .. code-block:: python + Returns: + A list of operators registered under the reputation network. + Returns an empty list if no operators are found. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils + Raises: + OperatorUtilsError: If the chain ID is invalid or the reputation address is malformed. - operators = OperatorUtils.get_reputation_network_operators( - ChainId.POLYGON_AMOY, - '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - ) - print(operators) + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.operator import OperatorUtils + + operators = OperatorUtils.get_reputation_network_operators( + ChainId.POLYGON_AMOY, + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + role="Recording Oracle", + ) + print(f"Found {len(operators)} operators") + ``` """ from human_protocol_sdk.gql.operator import get_reputation_network_query @@ -454,25 +513,35 @@ def get_rewards_info( slasher: str, options: Optional[SubgraphOptions] = None, ) -> List[RewardData]: - """Get rewards of the given slasher. + """Retrieve rewards collected by a slasher address. - :param chain_id: Network in which the slasher exists - :param slasher: Address of the slasher - :param options: Optional config for subgraph requests + Fetches all reward events where the specified address acted as a slasher + and received rewards for detecting misbehavior. - :return: List of rewards info + Args: + chain_id (ChainId): Network where the slasher operates. + slasher (str): Ethereum address of the slasher. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :example: - .. code-block:: python + Returns: + A list of rewards received by the slasher. + Returns an empty list if no rewards are found. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.operator import OperatorUtils + Raises: + OperatorUtilsError: If the chain ID is invalid or the slasher address is malformed. - rewards_info = OperatorUtils.get_rewards_info( - ChainId.POLYGON_AMOY, - '0x62dD51230A30401C455c8398d06F85e4EaB6309f' - ) - print(rewards_info) + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.operator import OperatorUtils + + rewards_info = OperatorUtils.get_rewards_info( + ChainId.POLYGON_AMOY, + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + ) + total_rewards = sum(reward.amount for reward in rewards_info) + print(f"Total rewards: {total_rewards}") + ``` """ if chain_id.value not in set(chain_id.value for chain_id in ChainId): diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py index 33a9073b53..c467b21ad8 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_client.py @@ -1,54 +1,25 @@ -""" -This client enables performing actions on staking contracts and -obtaining staking information from both the contracts and subgraph. - -Internally, the SDK will use one network or another according to the network ID of the web3. -To use this client, you need to create a Web3 instance and configure the default account, -as well as some middlewares. - -Code Example ------------- +"""Client for staking actions on HUMAN Protocol. -* With Signer - -.. code-block:: python +Internally selects network config based on the Web3 chain id. +Example: + ```python from eth_typing import URI from web3 import Web3 from web3.middleware import SignAndSendRawMiddlewareBuilder from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - -* Without Signer (For read operations only) - -.. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri - from human_protocol_sdk.staking import StakingClient w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) + gas_payer = w3.eth.account.from_key("YOUR_PRIVATE_KEY") + w3.eth.default_account = gas_payer.address + w3.middleware_onion.inject( + SignAndSendRawMiddlewareBuilder.build("YOUR_PRIVATE_KEY"), + "SignAndSendRawMiddlewareBuilder", + layer=0, + ) staking_client = StakingClient(w3) - -Module ------- + ``` """ import logging @@ -74,23 +45,46 @@ def get_w3_with_priv_key(priv_key: str): class StakingClientError(Exception): - """ - Raises when some error happens when interacting with staking. - """ + """Exception raised when errors occur during staking operations.""" pass class StakingClient: - """ - A class used to manage staking on the HUMAN network. - """ + """Client for interacting with the staking smart contract. - def __init__(self, w3: Web3): - """Initializes a Staking instance + This client provides methods to stake, unstake, withdraw, and slash HMT tokens, + as well as query staker information on the Human Protocol network. - :param w3: Web3 instance + Attributes: + w3 (Web3): Web3 instance configured for the target network. + network (dict): Network configuration for the current chain. + hmtoken_contract (Contract): Contract instance for the HMT token. + factory_contract (Contract): Contract instance for the escrow factory. + staking_contract (Contract): Contract instance for the staking contract. + """ + def __init__(self, w3: Web3): + """Initialize a StakingClient instance. + + Args: + w3 (Web3): Web3 instance configured for the target network. + Must have a valid provider and chain ID. + + Raises: + StakingClientError: If chain ID is invalid, network configuration is missing, + or network configuration is empty. + + Example: + ```python + from eth_typing import URI + from web3 import Web3 + from web3.providers.auto import load_provider_from_uri + from human_protocol_sdk.staking import StakingClient + + w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) + staking_client = StakingClient(w3) + ``` """ # Initialize web3 instance @@ -132,42 +126,29 @@ def __init__(self, w3: Web3): @requires_signer def approve_stake(self, amount: int, tx_options: Optional[TxParams] = None) -> None: - """Approves HMT token for Staking. - - :param amount: Amount to approve - :param tx_options: (Optional) Additional transaction parameters - - :return: None + """Approve HMT tokens for staking. - :validate: - Amount must be greater than 0 + Grants the staking contract permission to transfer HMT tokens from the caller's + account. This must be called before staking. - :example: - .. code-block:: python + Args: + amount (int): Amount of HMT tokens to approve in token's smallest unit + (must be greater than 0). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Returns: + None - from human_protocol_sdk.staking import StakingClient + Raises: + StakingClientError: If the amount is not positive or the transaction fails. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) + Example: + ```python + from web3 import Web3 - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - staking_client.approve_stake(amount) + amount = Web3.to_wei(100, "ether") + staking_client.approve_stake(amount) + ``` """ if amount <= 0: @@ -182,45 +163,44 @@ def get_w3_with_priv_key(priv_key: str): @requires_signer def stake(self, amount: int, tx_options: Optional[TxParams] = None) -> None: - """Stakes HMT token. - - :param amount: Amount to stake - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :validate: - - Amount must be greater than 0 - - Amount must be less than or equal to the approved amount (on-chain) - - Amount must be less than or equal to the balance of the staker (on-chain) - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) + """Stake HMT tokens. + + Deposits HMT tokens into the staking contract. The tokens must be approved first + using ``approve_stake()``. + + Args: + amount (int): Amount of HMT tokens to stake in token's smallest unit + (must be greater than 0 and within approved/balance limits). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + None + + Raises: + StakingClientError: If the amount is invalid or the transaction fails. + + Example: + ```python + from eth_typing import URI + from web3 import Web3 + from web3.middleware import SignAndSendRawMiddlewareBuilder + from web3.providers.auto import load_provider_from_uri + from human_protocol_sdk.staking import StakingClient + + w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) + gas_payer = w3.eth.account.from_key("YOUR_PRIVATE_KEY") + w3.eth.default_account = gas_payer.address + w3.middleware_onion.inject( + SignAndSendRawMiddlewareBuilder.build("YOUR_PRIVATE_KEY"), + "SignAndSendRawMiddlewareBuilder", + layer=0, + ) - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - staking_client.approve_stake(amount) # if it was already approved before, this is not necessary - staking_client.stake(amount) + staking_client = StakingClient(w3) + amount = Web3.to_wei(5, "ether") + staking_client.approve_stake(amount) + staking_client.stake(amount) + ``` """ if amount <= 0: @@ -233,43 +213,27 @@ def get_w3_with_priv_key(priv_key: str): @requires_signer def unstake(self, amount: int, tx_options: Optional[TxParams] = None) -> None: - """Unstakes HMT token. - - :param amount: Amount to unstake - :param tx_options: (Optional) Additional transaction parameters - - :return: None + """Unstake HMT tokens. - :validate: - - Amount must be greater than 0 - - Amount must be less than or equal to the staked amount which is not locked / allocated (on-chain) + Initiates the unstaking process for the specified amount. The tokens will be + locked for a period before they can be withdrawn. - :example: - .. code-block:: python + Args: + amount (int): Amount of HMT tokens to unstake in token's smallest unit + (must be greater than 0 and less than or equal to unlocked staked amount). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Returns: + None - from human_protocol_sdk.staking import StakingClient + Raises: + StakingClientError: If the amount is invalid or the transaction fails. - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - staking_client.unstake(amount) + Example: + ```python + amount = Web3.to_wei(5, "ether") + staking_client.unstake(amount) + ``` """ if amount <= 0: @@ -284,40 +248,24 @@ def get_w3_with_priv_key(priv_key: str): @requires_signer def withdraw(self, tx_options: Optional[TxParams] = None) -> None: - """Withdraws HMT token. - - :param tx_options: (Optional) Additional transaction parameters + """Withdraw unlocked unstaked HMT tokens. - :return: None + Withdraws all available unstaked tokens that have completed the unlocking period + and transfers them back to the caller's account. - :validate: - - There must be unstaked tokens which is unlocked (on-chain) + Args: + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. - :example: - .. code-block:: python + Returns: + None - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri + Raises: + StakingClientError: If the transaction fails or no tokens are available to withdraw. - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - staking_client.withdraw() + Example: + ```python + staking_client.withdraw() + ``` """ try: @@ -335,52 +283,35 @@ def slash( amount: int, tx_options: Optional[TxParams] = None, ) -> None: - """Slashes HMT token. - - :param slasher: Address of the slasher - :param staker: Address of the staker - :param escrow_address: Address of the escrow - :param amount: Amount to slash - :param tx_options: (Optional) Additional transaction parameters - - :return: None - - :validate: - - Amount must be greater than 0 - - Amount must be less than or equal to the amount allocated to the escrow (on-chain) - - Escrow address must be valid - - :example: - .. code-block:: python - - from eth_typing import URI - from web3 import Web3 - from web3.middleware import SignAndSendRawMiddlewareBuilder - from web3.providers.auto import load_provider_from_uri - - from human_protocol_sdk.staking import StakingClient - - def get_w3_with_priv_key(priv_key: str): - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - gas_payer = w3.eth.account.from_key(priv_key) - w3.eth.default_account = gas_payer.address - w3.middleware_onion.inject( - SignAndSendRawMiddlewareBuilder.build(priv_key), - 'SignAndSendRawMiddlewareBuilder', - layer=0, - ) - return (w3, gas_payer) - - (w3, gas_payer) = get_w3_with_priv_key('YOUR_PRIVATE_KEY') - staking_client = StakingClient(w3) - - amount = Web3.to_wei(5, 'ether') # convert from ETH to WEI - staking_client.slash( - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - '0x62dD51230A30401C455c8398d06F85e4EaB6309f', - amount - ) + """Slash a staker's stake for a given escrow. + + Penalizes a staker by reducing their staked amount and distributing rewards + to the slasher for detecting misbehavior or violations. + + Args: + slasher (str): Address of the entity performing the slash (receives rewards). + staker (str): Address of the staker to be slashed. + escrow_address (str): Address of the escrow associated with the violation. + amount (int): Amount to slash in token's smallest unit + (must be greater than 0 and within staker's allocation to the escrow). + tx_options (Optional[TxParams]): Optional transaction parameters such as gas limit. + + Returns: + None + + Raises: + StakingClientError: If the amount is invalid, escrow address is invalid, + or the transaction fails. + + Example: + ```python + staking_client.slash( + "0xSlasherAddress", + "0xStakerAddress", + "0xEscrowAddress", + Web3.to_wei(10, "ether"), + ) + ``` """ if amount <= 0: @@ -396,28 +327,32 @@ def get_w3_with_priv_key(priv_key: str): handle_error(e, StakingClientError) def get_staker_info(self, staker_address: str) -> dict: - """Retrieves comprehensive staking information for a staker. - - :param staker_address: The address of the staker - :return: A dictionary containing staker information + """Retrieve comprehensive staking information for a staker. - :validate: - - Staker address must be valid + Fetches on-chain staking data including staked amount, locked amount, + lock expiration, and withdrawable amount. - :example: - .. code-block:: python + Args: + staker_address (str): Ethereum address of the staker. - from eth_typing import URI - from web3 import Web3 - from web3.providers.auto import load_provider_from_uri + Returns: + Staker info with keys: - from human_protocol_sdk.staking import StakingClient + - `stakedAmount` (int): Total staked amount. + - `lockedAmount` (int): Currently locked amount. + - `lockedUntil` (int): Block number until tokens are locked (0 if unlocked). + - `withdrawableAmount` (int): Amount available for withdrawal. - w3 = Web3(load_provider_from_uri(URI("http://localhost:8545"))) - staking_client = StakingClient(w3) + Raises: + StakingClientError: If the staker address is invalid or the query fails. - staking_info = staking_client.get_staker_info('0xYourStakerAddress') - print(staking_info['stakedAmount']) + Example: + ```python + staking_info = staking_client.get_staker_info("0xYourStakerAddress") + print(f"Staked: {staking_info['stakedAmount']}") + print(f"Locked: {staking_info['lockedAmount']}") + print(f"Withdrawable: {staking_info['withdrawableAmount']}") + ``` """ if not Web3.is_address(staker_address): raise StakingClientError(f"Invalid staker address: {staker_address}") @@ -448,11 +383,16 @@ def get_staker_info(self, staker_address: str) -> dict: raise StakingClientError(f"Failed to get staker info: {str(e)}") def _is_valid_escrow(self, escrow_address: str) -> bool: - """Checks if the escrow address is valid. + """Check if an escrow address exists in the factory registry. + + Internal method to validate that an escrow address is registered with the + escrow factory contract. - :param escrow_address: Address of the escrow + Args: + escrow_address (str): Escrow address to validate. - :return: True if the escrow address is valid, False otherwise + Returns: + ``True`` if the escrow exists in the factory registry, ``False`` otherwise. """ # TODO: Use Escrow/Job Module once implemented diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_utils.py index 74915e278b..64fbbdd9ef 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/staking/staking_utils.py @@ -1,31 +1,4 @@ -""" -Utility class for staking-related operations. - -Code Example ------------- - -.. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.staking.staking_utils import StakingUtils, StakersFilter - - stakers = StakingUtils.get_stakers( - StakersFilter( - chain_id=ChainId.POLYGON_AMOY, - min_staked_amount="1000000000000000000", - max_locked_amount="5000000000000000000", - order_by="withdrawnAmount", - order_direction="asc", - first=5, - skip=0, - ) - ) - print("Filtered stakers:", stakers) - -Module ------- - -""" +"""Utility helpers for staking-related queries.""" from typing import List, Optional from human_protocol_sdk.constants import NETWORKS, ChainId @@ -35,6 +8,19 @@ class StakerData: + """Represents staker information retrieved from the subgraph. + + Attributes: + id (str): Unique staker identifier. + address (str): Staker's Ethereum address. + staked_amount (int): Total amount staked in token's smallest unit. + locked_amount (int): Amount currently locked. + withdrawn_amount (int): Total amount withdrawn. + slashed_amount (int): Total amount slashed. + locked_until_timestamp (int): Time in milliseconds until locked amount is released. + last_deposit_timestamp (int): Last deposit time in milliseconds. + """ + def __init__( self, id: str, @@ -57,16 +43,51 @@ def __init__( class StakingUtilsError(Exception): - pass + """Exception raised when staking utility operations fail.""" class StakingUtils: + """Utility class providing staking-related query and data retrieval functions. + + This class offers static methods to fetch staker data from the Human Protocol + subgraph, including individual staker details and filtered lists. + """ + @staticmethod def get_staker( chain_id: ChainId, address: str, options: Optional[SubgraphOptions] = None, ) -> Optional[StakerData]: + """Retrieve a single staker by their address. + + Fetches detailed staking information for a specific address from the subgraph. + + Args: + chain_id (ChainId): Network where the staker is registered. + address (str): Ethereum address of the staker. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + Staker data if found, otherwise ``None``. + + Raises: + StakingUtilsError: If the chain ID is not supported. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.staking import StakingUtils + + staker = StakingUtils.get_staker( + ChainId.POLYGON_AMOY, + "0x62dD51230A30401C455c8398d06F85e4EaB6309f", + ) + if staker: + print(f"Staked: {staker.staked_amount}") + print(f"Locked: {staker.locked_amount}") + ``` + """ network = NETWORKS.get(chain_id) if not network: raise StakingUtilsError("Unsupported Chain ID") @@ -102,6 +123,40 @@ def get_stakers( filter: StakersFilter, options: Optional[SubgraphOptions] = None, ) -> List[StakerData]: + """Retrieve a list of stakers matching the provided filter criteria. + + Queries the subgraph for stakers that match the specified parameters including + amount ranges, ordering, and pagination. + + Args: + filter (StakersFilter): Filter parameters including chain ID, amount ranges + (staked, locked, withdrawn, slashed), ordering, and pagination options. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + A list of staker records matching the filter criteria. + Returns an empty list if no matches are found. + + Raises: + StakingUtilsError: If the chain ID is not supported. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.staking import StakingUtils + from human_protocol_sdk.filter import StakersFilter + from web3 import Web3 + + stakers = StakingUtils.get_stakers( + StakersFilter( + chain_id=ChainId.POLYGON_AMOY, + min_staked_amount=Web3.to_wei(100, "ether"), + ) + ) + for staker in stakers: + print(f"{staker.address}: {staker.staked_amount}") + ``` + """ network_data = NETWORKS.get(filter.chain_id) if not network_data: raise StakingUtilsError("Unsupported Chain ID") diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_client.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_client.py deleted file mode 100644 index b78f927418..0000000000 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_client.py +++ /dev/null @@ -1,666 +0,0 @@ -""" -This client enables to obtain statistical information from the subgraph. - -Code Example ------------- - -.. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - -Module ------- -""" - -from datetime import datetime -import logging - -from typing import List, Optional - -from human_protocol_sdk.constants import ChainId, NETWORKS - -from human_protocol_sdk.utils import SubgraphOptions, custom_gql_fetch -from human_protocol_sdk.filter import StatisticsFilter - -LOG = logging.getLogger("human_protocol_sdk.statistics") - - -class StatisticsClientError(Exception): - """ - Raises when some error happens when getting data from subgraph. - """ - - pass - - -class HMTHoldersParam: - """ - A class used to specify parameters for querying HMT holders. - """ - - def __init__( - self, - address: str = None, - order_direction: str = "asc", - ): - """ - Initializes a HMTHoldersParam instance. - - :param address: Filter by holder's address - :param order_direction: Optional. Direction of sorting ('asc' for ascending, 'desc' for descending) - """ - self.address = address - self.order_direction = order_direction - - -class DailyEscrowData: - """ - A class used to specify daily escrow data. - """ - - def __init__( - self, - timestamp: datetime, - escrows_total: int, - escrows_pending: int, - escrows_solved: int, - escrows_paid: int, - escrows_cancelled: int, - ): - """ - Initializes a DailyEscrowData instance. - - :param timestamp: Timestamp - :param escrows_total: Total escrows - :param escrows_pending: Pending escrows - :param escrows_solved: Solved escrows - :param escrows_paid: Paid escrows - :param escrows_cancelled: Cancelled escrows - """ - - self.timestamp = timestamp - self.escrows_total = escrows_total - self.escrows_pending = escrows_pending - self.escrows_solved = escrows_solved - self.escrows_paid = escrows_paid - self.escrows_cancelled = escrows_cancelled - - -class EscrowStatistics: - """ - A class used to specify escrow statistics. - """ - - def __init__( - self, - total_escrows: int, - daily_escrows_data: List[DailyEscrowData], - ): - """ - Initializes a EscrowStatistics instance. - - :param total_escrows: Total escrows - :param daily_escrows_data: Daily escrows data - """ - - self.total_escrows = total_escrows - self.daily_escrows_data = daily_escrows_data - - -class DailyWorkerData: - """ - A class used to specify daily worker data. - """ - - def __init__( - self, - timestamp: datetime, - active_workers: int, - ): - """ - Initializes a DailyWorkerData instance. - - :param timestamp: Timestamp - :param active_workers: Active workers - """ - - self.timestamp = timestamp - self.active_workers = active_workers - - -class WorkerStatistics: - """ - A class used to specify worker statistics. - """ - - def __init__( - self, - daily_workers_data: List[DailyWorkerData], - ): - """ - Initializes a WorkerStatistics instance. - - :param daily_workers_data: Daily workers data - """ - - self.daily_workers_data = daily_workers_data - - -class DailyPaymentData: - """ - A class used to specify daily payment data. - """ - - def __init__( - self, - timestamp: datetime, - total_amount_paid: int, - total_count: int, - average_amount_per_worker: int, - ): - """ - Initializes a DailyPaymentData instance. - - :param timestamp: Timestamp - :param total_amount_paid: Total amount paid - :param total_count: Total count - :param average_amount_per_worker: Average amount per worker - """ - - self.timestamp = timestamp - self.total_amount_paid = total_amount_paid - self.total_count = total_count - self.average_amount_per_worker = average_amount_per_worker - - -class PaymentStatistics: - """ - A class used to specify payment statistics. - """ - - def __init__( - self, - daily_payments_data: List[DailyPaymentData], - ): - """ - Initializes a PaymentStatistics instance. - - :param daily_payments_data: Daily payments data - """ - - self.daily_payments_data = daily_payments_data - - -class HMTHolder: - """ - A class used to specify HMT holder. - """ - - def __init__( - self, - address: str, - balance: int, - ): - """ - Initializes a HMTHolder instance. - - :param address: Holder address - :param balance: Holder balance - """ - - self.address = address - self.balance = balance - - -class DailyHMTData: - """ - A class used to specify daily HMT data. - """ - - def __init__( - self, - timestamp: datetime, - total_transaction_amount: int, - total_transaction_count: int, - daily_unique_senders: int, - daily_unique_receivers: int, - ): - """ - Initializes a DailyHMTData instance. - - :param timestamp: Timestamp - :param total_transaction_amount: Total transaction amount - :param total_transaction_count: Total transaction count - :param daily_unique_senders: Total unique senders - :param daily_unique_receivers: Total unique receivers - """ - - self.timestamp = timestamp - self.total_transaction_amount = total_transaction_amount - self.total_transaction_count = total_transaction_count - self.daily_unique_senders = daily_unique_senders - self.daily_unique_receivers = daily_unique_receivers - - -class HMTStatistics: - """ - A class used to specify HMT statistics. - """ - - def __init__( - self, - total_transfer_amount: int, - total_transfer_count: int, - total_holders: int, - ): - """ - Initializes a HMTStatistics instance. - - :param total_transfer_amount: Total transfer amount - :param total_transfer_count: Total transfer count - :param total_holders: Total holders - """ - - self.total_transfer_amount = total_transfer_amount - self.total_transfer_count = total_transfer_count - self.total_holders = total_holders - - -class StatisticsClient: - """ - A client used to get statistical data. - """ - - def __init__(self, chain_id: ChainId = ChainId.POLYGON_AMOY): - """Initializes a Statistics instance - - :param chain_id: Chain ID to get statistical data from - - """ - - if chain_id.value not in [chain_id.value for chain_id in ChainId]: - raise StatisticsClientError(f"Invalid ChainId: {chain_id}") - - self.network = NETWORKS[ChainId(chain_id)] - - if not self.network: - raise StatisticsClientError("Empty network configuration") - - def get_escrow_statistics( - self, - filter: StatisticsFilter = StatisticsFilter(), - options: Optional[SubgraphOptions] = None, - ) -> EscrowStatistics: - """Get escrow statistics data for the given date range. - - :param filter: Object containing the date range - :param options: Optional config for subgraph requests - - :return: Escrow statistics data - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - from human_protocol_sdk.filter import StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_escrow_statistics()) - print( - statistics_client.get_escrow_statistics( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - """ - - from human_protocol_sdk.gql.statistics import ( - get_event_day_data_query, - get_escrow_statistics_query, - ) - - escrow_statistics_data = custom_gql_fetch( - self.network, - query=get_escrow_statistics_query, - options=options, - ) - escrow_statistics = escrow_statistics_data["data"]["escrowStatistics"] - - event_day_datas_data = custom_gql_fetch( - self.network, - query=get_event_day_data_query(filter), - params={ - "from": int(filter.date_from.timestamp()) if filter.date_from else None, - "to": int(filter.date_to.timestamp()) if filter.date_to else None, - "first": filter.first, - "skip": filter.skip, - "orderDirection": filter.order_direction.value, - }, - options=options, - ) - event_day_datas = event_day_datas_data["data"]["eventDayDatas"] - - return EscrowStatistics( - total_escrows=int(escrow_statistics.get("totalEscrowCount", 0)), - daily_escrows_data=[ - DailyEscrowData( - timestamp=datetime.fromtimestamp( - int(event_day_data.get("timestamp", 0)) - ), - escrows_total=int(event_day_data.get("dailyEscrowCount", 0)), - escrows_pending=int( - event_day_data.get("dailyPendingStatusEventCount", 0) - ), - escrows_solved=int( - event_day_data.get("dailyCompletedStatusEventCount", 0) - ), - escrows_paid=int( - event_day_data.get("dailyPaidStatusEventCount", 0) - ), - escrows_cancelled=int( - event_day_data.get("dailyCancelledStatusEventCount", 0) - ), - ) - for event_day_data in event_day_datas - ], - ) - - def get_worker_statistics( - self, - filter: StatisticsFilter = StatisticsFilter(), - options: Optional[SubgraphOptions] = None, - ) -> WorkerStatistics: - """Get worker statistics data for the given date range. - - :param filter: Object containing the date range - :param options: Optional config for subgraph requests - - :return: Worker statistics data - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - from human_protocol_sdk.filter import StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_worker_statistics()) - print( - statistics_client.get_worker_statistics( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - """ - from human_protocol_sdk.gql.statistics import ( - get_event_day_data_query, - ) - - event_day_datas_data = custom_gql_fetch( - self.network, - query=get_event_day_data_query(filter), - params={ - "from": int(filter.date_from.timestamp()) if filter.date_from else None, - "to": int(filter.date_to.timestamp()) if filter.date_to else None, - "first": filter.first, - "skip": filter.skip, - "orderDirection": filter.order_direction.value, - }, - options=options, - ) - event_day_datas = event_day_datas_data["data"]["eventDayDatas"] - - return WorkerStatistics( - daily_workers_data=[ - DailyWorkerData( - timestamp=datetime.fromtimestamp( - int(event_day_data.get("timestamp", 0)) - ), - active_workers=int(event_day_data.get("dailyWorkerCount", 0)), - ) - for event_day_data in event_day_datas - ], - ) - - def get_payment_statistics( - self, - filter: StatisticsFilter = StatisticsFilter(), - options: Optional[SubgraphOptions] = None, - ) -> PaymentStatistics: - """Get payment statistics data for the given date range. - - :param filter: Object containing the date range - :param options: Optional config for subgraph requests - - :return: Payment statistics data - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - from human_protocol_sdk.filter import StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_payment_statistics()) - print( - statistics_client.get_payment_statistics( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - """ - - from human_protocol_sdk.gql.statistics import ( - get_event_day_data_query, - ) - - event_day_datas_data = custom_gql_fetch( - self.network, - query=get_event_day_data_query(filter), - params={ - "from": int(filter.date_from.timestamp()) if filter.date_from else None, - "to": int(filter.date_to.timestamp()) if filter.date_to else None, - "first": filter.first, - "skip": filter.skip, - "orderDirection": filter.order_direction.value, - }, - options=options, - ) - event_day_datas = event_day_datas_data["data"]["eventDayDatas"] - - return PaymentStatistics( - daily_payments_data=[ - DailyPaymentData( - timestamp=datetime.fromtimestamp( - int(event_day_data.get("timestamp", 0)) - ), - total_amount_paid=int( - event_day_data.get("dailyHMTPayoutAmount", 0) - ), - total_count=int(event_day_data.get("dailyPayoutCount", 0)), - average_amount_per_worker=( - int(event_day_data.get("dailyHMTPayoutAmount", 0)) - / int(event_day_data.get("dailyWorkerCount")) - if event_day_data.get("dailyWorkerCount", "0") != "0" - else 0 - ), - ) - for event_day_data in event_day_datas - ], - ) - - def get_hmt_statistics( - self, options: Optional[SubgraphOptions] = None - ) -> HMTStatistics: - """Get HMT statistics data. - - :param options: Optional config for subgraph requests - - :return: HMT statistics data - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_hmt_statistics()) - """ - from human_protocol_sdk.gql.statistics import ( - get_event_day_data_query, - get_hmtoken_statistics_query, - ) - - hmtoken_statistics_data = custom_gql_fetch( - self.network, - query=get_hmtoken_statistics_query, - options=options, - ) - hmtoken_statistics = hmtoken_statistics_data["data"]["hmtokenStatistics"] - - return HMTStatistics( - total_transfer_amount=int( - hmtoken_statistics.get("totalValueTransfered", 0) - ), - total_transfer_count=int( - hmtoken_statistics.get("totalTransferEventCount", 0) - ), - total_holders=int(hmtoken_statistics.get("holders", 0)), - ) - - def get_hmt_holders( - self, - param: HMTHoldersParam = HMTHoldersParam(), - options: Optional[SubgraphOptions] = None, - ) -> List[HMTHolder]: - """Get HMT holders data with optional filters and ordering. - - :param param: Object containing filter and order parameters - :param options: Optional config for subgraph requests - - :return: List of HMT holders - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient, HMTHoldersParam - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_hmt_holders()) - print( - statistics_client.get_hmt_holders( - HMTHoldersParam( - address="0x123...", - order_direction="asc", - ) - ) - ) - """ - from human_protocol_sdk.gql.hmtoken import get_holders_query - - holders_data = custom_gql_fetch( - self.network, - query=get_holders_query(address=param.address), - params={ - "address": param.address, - "orderBy": "balance", - "orderDirection": param.order_direction, - }, - options=options, - ) - - holders = holders_data["data"]["holders"] - - return [ - HMTHolder( - address=holder.get("address", ""), - balance=int(holder.get("balance", 0)), - ) - for holder in holders - ] - - def get_hmt_daily_data( - self, - filter: StatisticsFilter = StatisticsFilter(), - options: Optional[SubgraphOptions] = None, - ) -> List[DailyHMTData]: - """Get HMT daily statistics data for the given date range. - - :param filter: Object containing the date range - :param options: Optional config for subgraph requests - - :return: HMT statistics data - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.statistics import StatisticsClient, StatisticsFilter - - statistics_client = StatisticsClient(ChainId.POLYGON_AMOY) - - print(statistics_client.get_hmt_daily_data()) - print( - statistics_client.get_hmt_daily_data( - StatisticsFilter( - date_from=datetime.datetime(2023, 5, 8), - date_to=datetime.datetime(2023, 6, 8), - ) - ) - ) - """ - from human_protocol_sdk.gql.statistics import ( - get_event_day_data_query, - ) - - event_day_datas_data = custom_gql_fetch( - self.network, - query=get_event_day_data_query(filter), - params={ - "from": int(filter.date_from.timestamp()) if filter.date_from else None, - "to": int(filter.date_to.timestamp()) if filter.date_to else None, - "first": filter.first, - "skip": filter.skip, - "orderDirection": filter.order_direction.value, - }, - options=options, - ) - event_day_datas = event_day_datas_data["data"]["eventDayDatas"] - - return [ - DailyHMTData( - timestamp=datetime.fromtimestamp( - int(event_day_data.get("timestamp", 0)) - ), - total_transaction_amount=int( - event_day_data.get("dailyHMTTransferAmount", 0) - ), - total_transaction_count=int( - event_day_data.get("dailyHMTTransferCount", 0) - ), - daily_unique_senders=int(event_day_data.get("dailyUniqueSenders", 0)), - daily_unique_receivers=int( - event_day_data.get("dailyUniqueReceivers", 0) - ), - ) - for event_day_data in event_day_datas - ] diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_utils.py new file mode 100644 index 0000000000..5d79cb567a --- /dev/null +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/statistics/statistics_utils.py @@ -0,0 +1,712 @@ +"""Utility helpers for retrieving statistics information. + +Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils + + stats = StatisticsUtils.get_escrow_statistics(ChainId.POLYGON_AMOY) + ``` +""" + +from datetime import datetime +import logging + +from typing import List, Optional + +from human_protocol_sdk.constants import ChainId, NETWORKS + +from human_protocol_sdk.utils import SubgraphOptions, custom_gql_fetch +from human_protocol_sdk.filter import StatisticsFilter + +LOG = logging.getLogger("human_protocol_sdk.statistics") + + +class StatisticsUtilsError(Exception): + """Exception raised when errors occur during statistics operations.""" + + pass + + +class HMTHoldersParam: + """Filter parameters for querying HMT token holders. + + Attributes: + address (Optional[str]): Optional holder address to filter by. + order_direction (str): Sort direction - either "asc" or "desc". + """ + + def __init__( + self, + address: str = None, + order_direction: str = "asc", + ): + self.address = address + self.order_direction = order_direction + + +class DailyEscrowData: + """Represents aggregated escrow metrics for a single day. + + Attributes: + timestamp (datetime): Day boundary timestamp. + escrows_total (int): Total number of escrows created on this day. + escrows_pending (int): Number of escrows in pending status. + escrows_solved (int): Number of escrows that were solved/completed. + escrows_paid (int): Number of escrows that were paid out. + escrows_cancelled (int): Number of escrows that were cancelled. + """ + + def __init__( + self, + timestamp: datetime, + escrows_total: int, + escrows_pending: int, + escrows_solved: int, + escrows_paid: int, + escrows_cancelled: int, + ): + self.timestamp = timestamp + self.escrows_total = escrows_total + self.escrows_pending = escrows_pending + self.escrows_solved = escrows_solved + self.escrows_paid = escrows_paid + self.escrows_cancelled = escrows_cancelled + + +class EscrowStatistics: + """Aggregate escrow statistics data. + + Attributes: + total_escrows (int): Total number of escrows across all time. + daily_escrows_data (List[DailyEscrowData]): Daily breakdown of escrow metrics. + """ + + def __init__( + self, + total_escrows: int, + daily_escrows_data: List[DailyEscrowData], + ): + self.total_escrows = total_escrows + self.daily_escrows_data = daily_escrows_data + + +class DailyWorkerData: + """Represents aggregated worker metrics for a single day. + + Attributes: + timestamp (datetime): Day boundary timestamp. + active_workers (int): Number of active workers on this day. + """ + + def __init__( + self, + timestamp: datetime, + active_workers: int, + ): + self.timestamp = timestamp + self.active_workers = active_workers + + +class WorkerStatistics: + """Aggregate worker statistics data. + + Attributes: + daily_workers_data (List[DailyWorkerData]): Daily breakdown of worker metrics. + """ + + def __init__( + self, + daily_workers_data: List[DailyWorkerData], + ): + self.daily_workers_data = daily_workers_data + + +class DailyPaymentData: + """Represents aggregated payment metrics for a single day. + + Attributes: + timestamp (datetime): Day boundary timestamp. + total_amount_paid (int): Total amount paid out on this day. + total_count (int): Number of payment transactions. + average_amount_per_worker (int): Average payout amount per worker. + """ + + def __init__( + self, + timestamp: datetime, + total_amount_paid: int, + total_count: int, + average_amount_per_worker: int, + ): + self.timestamp = timestamp + self.total_amount_paid = total_amount_paid + self.total_count = total_count + self.average_amount_per_worker = average_amount_per_worker + + +class PaymentStatistics: + """Aggregate payment statistics data. + + Attributes: + daily_payments_data (List[DailyPaymentData]): Daily breakdown of payment metrics. + """ + + def __init__( + self, + daily_payments_data: List[DailyPaymentData], + ): + self.daily_payments_data = daily_payments_data + + +class HMTHolder: + """Represents an HMT token holder. + + Attributes: + address (str): Ethereum address of the holder. + balance (int): Token balance in smallest unit. + """ + + def __init__( + self, + address: str, + balance: int, + ): + self.address = address + self.balance = balance + + +class DailyHMTData: + """Represents aggregated HMT transfer metrics for a single day. + + Attributes: + timestamp (datetime): Day boundary timestamp. + total_transaction_amount (int): Total amount transferred on this day. + total_transaction_count (int): Number of transfer transactions. + daily_unique_senders (int): Number of unique addresses sending tokens. + daily_unique_receivers (int): Number of unique addresses receiving tokens. + """ + + def __init__( + self, + timestamp: datetime, + total_transaction_amount: int, + total_transaction_count: int, + daily_unique_senders: int, + daily_unique_receivers: int, + ): + self.timestamp = timestamp + self.total_transaction_amount = total_transaction_amount + self.total_transaction_count = total_transaction_count + self.daily_unique_senders = daily_unique_senders + self.daily_unique_receivers = daily_unique_receivers + + +class HMTStatistics: + """Aggregate HMT token statistics. + + Attributes: + total_transfer_amount (int): Total amount transferred across all time. + total_transfer_count (int): Total number of transfer transactions. + total_holders (int): Total number of token holders. + """ + + def __init__( + self, + total_transfer_amount: int, + total_transfer_count: int, + total_holders: int, + ): + self.total_transfer_amount = total_transfer_amount + self.total_transfer_count = total_transfer_count + self.total_holders = total_holders + + +class StatisticsUtils: + """Utility class providing statistical data retrieval functions. + + This class offers static methods to fetch various statistics from the Human Protocol + subgraph, including escrow metrics, worker activity, payment data, and HMT token statistics. + """ + + @staticmethod + def get_escrow_statistics( + chain_id: ChainId, + filter: StatisticsFilter = StatisticsFilter(), + options: Optional[SubgraphOptions] = None, + ) -> EscrowStatistics: + """Retrieve escrow statistics for a given date range. + + Fetches aggregate escrow data including total counts and daily breakdowns + of escrow creation and status changes. + + Args: + chain_id (ChainId): Network to retrieve statistics from. + filter (StatisticsFilter): Date range and pagination filter. Defaults to all-time data. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + Escrow statistics including total count and daily data. + + Raises: + StatisticsUtilsError: If the chain ID is invalid or network configuration is missing. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils + from human_protocol_sdk.filter import StatisticsFilter + import datetime + + # Get all-time statistics + stats = StatisticsUtils.get_escrow_statistics(ChainId.POLYGON_AMOY) + print(f"Total escrows: {stats.total_escrows}") + + # Get statistics for specific date range + stats = StatisticsUtils.get_escrow_statistics( + ChainId.POLYGON_AMOY, + StatisticsFilter( + date_from=datetime.datetime(2023, 5, 8), + date_to=datetime.datetime(2023, 6, 8), + ) + ) + for day_data in stats.daily_escrows_data: + print(f"{day_data.timestamp}: {day_data.escrows_total} escrows") + ``` + """ + if chain_id.value not in [cid.value for cid in ChainId]: + raise StatisticsUtilsError(f"Invalid ChainId: {chain_id}") + + network = NETWORKS.get(chain_id) + if not network: + raise StatisticsUtilsError("Empty network configuration") + + from human_protocol_sdk.gql.statistics import ( + get_event_day_data_query, + get_escrow_statistics_query, + ) + + escrow_statistics_data = custom_gql_fetch( + network, + query=get_escrow_statistics_query, + options=options, + ) + escrow_statistics = escrow_statistics_data["data"]["escrowStatistics"] + + event_day_datas_data = custom_gql_fetch( + network, + query=get_event_day_data_query(filter), + params={ + "from": int(filter.date_from.timestamp()) if filter.date_from else None, + "to": int(filter.date_to.timestamp()) if filter.date_to else None, + "first": filter.first, + "skip": filter.skip, + "orderDirection": filter.order_direction.value, + }, + options=options, + ) + event_day_datas = event_day_datas_data["data"]["eventDayDatas"] + + return EscrowStatistics( + total_escrows=int(escrow_statistics.get("totalEscrowCount", 0)), + daily_escrows_data=[ + DailyEscrowData( + timestamp=datetime.fromtimestamp( + int(event_day_data.get("timestamp", 0)) + ), + escrows_total=int(event_day_data.get("dailyEscrowCount", 0)), + escrows_pending=int( + event_day_data.get("dailyPendingStatusEventCount", 0) + ), + escrows_solved=int( + event_day_data.get("dailyCompletedStatusEventCount", 0) + ), + escrows_paid=int( + event_day_data.get("dailyPaidStatusEventCount", 0) + ), + escrows_cancelled=int( + event_day_data.get("dailyCancelledStatusEventCount", 0) + ), + ) + for event_day_data in event_day_datas + ], + ) + + @staticmethod + def get_worker_statistics( + chain_id: ChainId, + filter: StatisticsFilter = StatisticsFilter(), + options: Optional[SubgraphOptions] = None, + ) -> WorkerStatistics: + """Retrieve worker activity statistics for a given date range. + + Fetches daily worker activity metrics showing the number of active workers + participating in escrows. + + Args: + chain_id (ChainId): Network to retrieve statistics from. + filter (StatisticsFilter): Date range and pagination filter. Defaults to all-time data. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + Worker statistics with daily activity breakdown. + + Raises: + StatisticsUtilsError: If the chain ID is invalid or network configuration is missing. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils + from human_protocol_sdk.filter import StatisticsFilter + import datetime + + stats = StatisticsUtils.get_worker_statistics( + ChainId.POLYGON_AMOY, + StatisticsFilter( + date_from=datetime.datetime(2023, 5, 8), + date_to=datetime.datetime(2023, 6, 8), + ) + ) + for day_data in stats.daily_workers_data: + print(f"{day_data.timestamp}: {day_data.active_workers} workers") + ``` + """ + if chain_id.value not in [cid.value for cid in ChainId]: + raise StatisticsUtilsError(f"Invalid ChainId: {chain_id}") + + network = NETWORKS.get(chain_id) + if not network: + raise StatisticsUtilsError("Empty network configuration") + + from human_protocol_sdk.gql.statistics import ( + get_event_day_data_query, + ) + + event_day_datas_data = custom_gql_fetch( + network, + query=get_event_day_data_query(filter), + params={ + "from": int(filter.date_from.timestamp()) if filter.date_from else None, + "to": int(filter.date_to.timestamp()) if filter.date_to else None, + "first": filter.first, + "skip": filter.skip, + "orderDirection": filter.order_direction.value, + }, + options=options, + ) + event_day_datas = event_day_datas_data["data"]["eventDayDatas"] + + return WorkerStatistics( + daily_workers_data=[ + DailyWorkerData( + timestamp=datetime.fromtimestamp( + int(event_day_data.get("timestamp", 0)) + ), + active_workers=int(event_day_data.get("dailyWorkerCount", 0)), + ) + for event_day_data in event_day_datas + ], + ) + + @staticmethod + def get_payment_statistics( + chain_id: ChainId, + filter: StatisticsFilter = StatisticsFilter(), + options: Optional[SubgraphOptions] = None, + ) -> PaymentStatistics: + """Retrieve payment statistics for a given date range. + + Fetches daily payment metrics including total amounts paid, transaction counts, + and average payment per worker. + + Args: + chain_id (ChainId): Network to retrieve statistics from. + filter (StatisticsFilter): Date range and pagination filter. Defaults to all-time data. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + Payment statistics with daily breakdown. + + Raises: + StatisticsUtilsError: If the chain ID is invalid or network configuration is missing. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils + from human_protocol_sdk.filter import StatisticsFilter + import datetime + + stats = StatisticsUtils.get_payment_statistics( + ChainId.POLYGON_AMOY, + StatisticsFilter( + date_from=datetime.datetime(2023, 5, 8), + date_to=datetime.datetime(2023, 6, 8), + ) + ) + for day_data in stats.daily_payments_data: + print(f"{day_data.timestamp}: {day_data.total_amount_paid} paid") + print(f" Average per worker: {day_data.average_amount_per_worker}") + ``` + """ + if chain_id.value not in [cid.value for cid in ChainId]: + raise StatisticsUtilsError(f"Invalid ChainId: {chain_id}") + + network = NETWORKS.get(chain_id) + if not network: + raise StatisticsUtilsError("Empty network configuration") + + from human_protocol_sdk.gql.statistics import ( + get_event_day_data_query, + ) + + event_day_datas_data = custom_gql_fetch( + network, + query=get_event_day_data_query(filter), + params={ + "from": int(filter.date_from.timestamp()) if filter.date_from else None, + "to": int(filter.date_to.timestamp()) if filter.date_to else None, + "first": filter.first, + "skip": filter.skip, + "orderDirection": filter.order_direction.value, + }, + options=options, + ) + event_day_datas = event_day_datas_data["data"]["eventDayDatas"] + + return PaymentStatistics( + daily_payments_data=[ + DailyPaymentData( + timestamp=datetime.fromtimestamp( + int(event_day_data.get("timestamp", 0)) + ), + total_amount_paid=int( + event_day_data.get("dailyHMTPayoutAmount", 0) + ), + total_count=int(event_day_data.get("dailyPayoutCount", 0)), + average_amount_per_worker=( + int(event_day_data.get("dailyHMTPayoutAmount", 0)) + / int(event_day_data.get("dailyWorkerCount")) + if event_day_data.get("dailyWorkerCount", "0") != "0" + else 0 + ), + ) + for event_day_data in event_day_datas + ], + ) + + @staticmethod + def get_hmt_statistics( + chain_id: ChainId, options: Optional[SubgraphOptions] = None + ) -> HMTStatistics: + """Retrieve aggregate HMT token statistics. + + Fetches overall HMT token metrics including total transfers and holder counts. + + Args: + chain_id (ChainId): Network to retrieve statistics from. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + Aggregate HMT token statistics. + + Raises: + StatisticsUtilsError: If the chain ID is invalid or network configuration is missing. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils + + stats = StatisticsUtils.get_hmt_statistics(ChainId.POLYGON_AMOY) + print(f"Total holders: {stats.total_holders}") + print(f"Total transfers: {stats.total_transfer_count}") + print(f"Total amount transferred: {stats.total_transfer_amount}") + ``` + """ + if chain_id.value not in [cid.value for cid in ChainId]: + raise StatisticsUtilsError(f"Invalid ChainId: {chain_id}") + + network = NETWORKS.get(chain_id) + if not network: + raise StatisticsUtilsError("Empty network configuration") + + from human_protocol_sdk.gql.statistics import ( + get_hmtoken_statistics_query, + ) + + hmtoken_statistics_data = custom_gql_fetch( + network, + query=get_hmtoken_statistics_query, + options=options, + ) + hmtoken_statistics = hmtoken_statistics_data["data"]["hmtokenStatistics"] + + return HMTStatistics( + total_transfer_amount=int( + hmtoken_statistics.get("totalValueTransfered", 0) + ), + total_transfer_count=int( + hmtoken_statistics.get("totalTransferEventCount", 0) + ), + total_holders=int(hmtoken_statistics.get("holders", 0)), + ) + + @staticmethod + def get_hmt_holders( + chain_id: ChainId, + param: HMTHoldersParam = HMTHoldersParam(), + options: Optional[SubgraphOptions] = None, + ) -> List[HMTHolder]: + """Retrieve HMT token holders with optional filters and ordering. + + Fetches a list of addresses holding HMT tokens with their balances. + + Args: + chain_id (ChainId): Network to retrieve holder data from. + param (HMTHoldersParam): Filter parameters and sort preferences. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + List of token holders with addresses and balances. + + Raises: + StatisticsUtilsError: If the chain ID is invalid or network configuration is missing. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils, HMTHoldersParam + + # Get all holders sorted by balance ascending + holders = StatisticsUtils.get_hmt_holders(ChainId.POLYGON_AMOY) + for holder in holders: + print(f"{holder.address}: {holder.balance}") + + # Get specific holder + holders = StatisticsUtils.get_hmt_holders( + ChainId.POLYGON_AMOY, + HMTHoldersParam( + address="0x123...", + order_direction="desc", + ) + ) + ``` + """ + if chain_id.value not in [cid.value for cid in ChainId]: + raise StatisticsUtilsError(f"Invalid ChainId: {chain_id}") + + network = NETWORKS.get(chain_id) + if not network: + raise StatisticsUtilsError("Empty network configuration") + + from human_protocol_sdk.gql.hmtoken import get_holders_query + + holders_data = custom_gql_fetch( + network, + query=get_holders_query(address=param.address), + params={ + "address": param.address, + "orderBy": "balance", + "orderDirection": param.order_direction, + }, + options=options, + ) + + holders = holders_data["data"]["holders"] + + return [ + HMTHolder( + address=holder.get("address", ""), + balance=int(holder.get("balance", 0)), + ) + for holder in holders + ] + + @staticmethod + def get_hmt_daily_data( + chain_id: ChainId, + filter: StatisticsFilter = StatisticsFilter(), + options: Optional[SubgraphOptions] = None, + ) -> List[DailyHMTData]: + """Retrieve daily HMT token transfer statistics for a given date range. + + Fetches daily metrics about HMT token transfers including amounts, counts, + and unique participants. + + Args: + chain_id (ChainId): Network to retrieve statistics from. + filter (StatisticsFilter): Date range and pagination filter. Defaults to all-time data. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + List of daily HMT transfer statistics. + + Raises: + StatisticsUtilsError: If the chain ID is invalid or network configuration is missing. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.statistics import StatisticsUtils + from human_protocol_sdk.filter import StatisticsFilter + import datetime + + daily_data = StatisticsUtils.get_hmt_daily_data( + ChainId.POLYGON_AMOY, + StatisticsFilter( + date_from=datetime.datetime(2023, 5, 8), + date_to=datetime.datetime(2023, 6, 8), + ) + ) + for day in daily_data: + print(f"{day.timestamp}:") + print(f" Transfers: {day.total_transaction_count}") + print(f" Amount: {day.total_transaction_amount}") + print(f" Unique senders: {day.daily_unique_senders}") + ``` + """ + if chain_id.value not in [cid.value for cid in ChainId]: + raise StatisticsUtilsError(f"Invalid ChainId: {chain_id}") + + network = NETWORKS.get(chain_id) + if not network: + raise StatisticsUtilsError("Empty network configuration") + + from human_protocol_sdk.gql.statistics import ( + get_event_day_data_query, + ) + + event_day_datas_data = custom_gql_fetch( + network, + query=get_event_day_data_query(filter), + params={ + "from": int(filter.date_from.timestamp()) if filter.date_from else None, + "to": int(filter.date_to.timestamp()) if filter.date_to else None, + "first": filter.first, + "skip": filter.skip, + "orderDirection": filter.order_direction.value, + }, + options=options, + ) + event_day_datas = event_day_datas_data["data"]["eventDayDatas"] + + return [ + DailyHMTData( + timestamp=datetime.fromtimestamp( + int(event_day_data.get("timestamp", 0)) + ), + total_transaction_amount=int( + event_day_data.get("dailyHMTTransferAmount", 0) + ), + total_transaction_count=int( + event_day_data.get("dailyHMTTransferCount", 0) + ), + daily_unique_senders=int(event_day_data.get("dailyUniqueSenders", 0)), + daily_unique_receivers=int( + event_day_data.get("dailyUniqueReceivers", 0) + ), + ) + for event_day_data in event_day_datas + ] diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py index ee725ff1b0..e3ac51f7ae 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/transaction/transaction_utils.py @@ -1,28 +1,20 @@ -""" -Utility class for transaction-related operations. - -Code Example ------------- - -.. code-block:: python +"""Utility helpers for transaction-related queries. +Example: + ```python from human_protocol_sdk.constants import ChainId from human_protocol_sdk.transaction import TransactionUtils, TransactionFilter - print( - TransactionUtils.get_transactions( - TransactionFilter( - chain_id=ChainId.POLYGON_AMOY, - from_address="0x1234567890123456789012345678901234567890", - to_address="0x0987654321098765432109876543210987654321", - start_date=datetime.datetime(2023, 5, 8), - end_date=datetime.datetime(2023, 6, 8), - ) + TransactionUtils.get_transactions( + TransactionFilter( + chain_id=ChainId.POLYGON_AMOY, + from_address="0x1234567890123456789012345678901234567890", + to_address="0x0987654321098765432109876543210987654321", + start_date=datetime.datetime(2023, 5, 8), + end_date=datetime.datetime(2023, 6, 8), ) ) - -Module ------- + ``` """ from typing import List, Optional @@ -34,6 +26,21 @@ class InternalTransaction: + """Represents an internal transaction within a parent transaction. + + Internal transactions are contract-to-contract calls that occur within + the execution of a main transaction. + + Attributes: + from_address (str): Source address of the internal transaction. + to_address (str): Destination address of the internal transaction. + value (int): Value transferred in token's smallest unit. + method (str): Method signature called in the internal transaction. + receiver (Optional[str]): Receiver address if applicable. + escrow (Optional[str]): Escrow address if the transaction involves an escrow. + token (Optional[str]): Token address if the transaction involves a token transfer. + """ + def __init__( self, from_address: str, @@ -54,6 +61,23 @@ def __init__( class TransactionData: + """Represents on-chain transaction data retrieved from the subgraph. + + Attributes: + chain_id (ChainId): Chain where the transaction was executed. + block (int): Block number containing the transaction. + tx_hash (str): Transaction hash. + from_address (str): Sender address. + to_address (str): Recipient address (contract or EOA). + timestamp (int): Transaction timestamp in milliseconds. + value (int): Value transferred in the main transaction. + method (str): Method signature of the transaction. + receiver (Optional[str]): Receiver address if applicable. + escrow (Optional[str]): Escrow address if the transaction involves an escrow. + token (Optional[str]): Token address if the transaction involves a token transfer. + internal_transactions (List[InternalTransaction]): List of internal transactions. + """ + def __init__( self, chain_id: ChainId, @@ -84,42 +108,55 @@ def __init__( class TransactionUtilsError(Exception): - """ - Raises when some error happens when getting data from subgraph. - """ + """Exception raised when transaction lookup or query operations fail.""" pass class TransactionUtils: - """ - A utility class that provides additional transaction-related functionalities. + """Utility class providing transaction query functions from the subgraph. + + This class offers static methods to fetch on-chain transaction data including + individual transactions by hash and filtered transaction lists with support for + internal transactions. """ @staticmethod def get_transaction( chain_id: ChainId, hash: str, options: Optional[SubgraphOptions] = None ) -> Optional[TransactionData]: - """Returns the transaction for a given hash. + """Retrieve a single transaction by its hash. - :param chain_id: Network in which the transaction was executed - :param hash: Hash of the transaction - :param options: Optional config for subgraph requests + Fetches detailed transaction information including internal transactions + from the subgraph. - :return: Transaction data + Args: + chain_id (ChainId): Network where the transaction was executed. + hash (str): Transaction hash to look up. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :example: - .. code-block:: python + Returns: + Transaction data if found, otherwise ``None``. - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.transaction import TransactionUtils + Raises: + TransactionUtilsError: If the chain ID is not supported. - print( - TransactionUtils.get_transaction( - ChainId.POLYGON_AMOY, - "0x1234567890123456789012345678901234567891" - ) - ) + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.transaction import TransactionUtils + + tx = TransactionUtils.get_transaction( + ChainId.POLYGON_AMOY, + "0x1234567890123456789012345678901234567890abcdef1234567890abcdef12", + ) + if tx: + print(f"Block: {tx.block}") + print(f"From: {tx.from_address}") + print(f"To: {tx.to_address}") + print(f"Value: {tx.value}") + print(f"Internal txs: {len(tx.internal_transactions)}") + ``` """ network = NETWORKS.get(chain_id) if not network: @@ -173,33 +210,63 @@ def get_transaction( def get_transactions( filter: TransactionFilter, options: Optional[SubgraphOptions] = None ) -> List[TransactionData]: - """Get an array of transactions based on the specified filter parameters. - - :param filter: Object containing all the necessary parameters to filter - (chain_id, from_address, to_address, start_date, end_date, start_block, end_block, method, escrow, token, first, skip, order_direction) - :param options: Optional config for subgraph requests - - :return: List of transactions - - :example: - .. code-block:: python - - from human_protocol_sdk.constants import ChainId - from human_protocol_sdk.transaction import TransactionUtils, TransactionFilter - - print( - TransactionUtils.get_transactions( - TransactionFilter( - chain_id=ChainId.POLYGON_AMOY, - from_address="0x1234567890123456789012345678901234567890", - to_address="0x0987654321098765432109876543210987654321", - method="transfer", - escrow="0x0987654321098765432109876543210987654321", - start_date=datetime.datetime(2023, 5, 8), - end_date=datetime.datetime(2023, 6, 8), - ) - ) + """Retrieve a list of transactions matching the provided filter criteria. + + Queries the subgraph for transactions that match the specified parameters + including addresses, date/block ranges, method signatures, and related contracts. + + Args: + filter (TransactionFilter): Filter parameters including chain ID, sender/recipient + addresses, date/block ranges, method signature, escrow address, token address, + pagination, and sorting options. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. + + Returns: + A list of transactions matching the filter criteria. + Returns an empty list if no matches are found. + + Raises: + TransactionUtilsError: If the chain ID is not supported. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.transaction import TransactionUtils, TransactionFilter + import datetime + + # Get all transactions from a specific address + txs = TransactionUtils.get_transactions( + TransactionFilter( + chain_id=ChainId.POLYGON_AMOY, + from_address="0x1234567890123456789012345678901234567890", + ) + ) + + # Get transactions within a date range with method filter + txs = TransactionUtils.get_transactions( + TransactionFilter( + chain_id=ChainId.POLYGON_AMOY, + from_address="0x1234567890123456789012345678901234567890", + to_address="0x0987654321098765432109876543210987654321", + method="transfer", + start_date=datetime.datetime(2023, 5, 8), + end_date=datetime.datetime(2023, 6, 8), + ) + ) + + # Get transactions involving specific escrow + txs = TransactionUtils.get_transactions( + TransactionFilter( + chain_id=ChainId.POLYGON_AMOY, + escrow="0x0987654321098765432109876543210987654321", + start_block=1000000, + end_block=2000000, ) + ) + + for tx in txs: + print(f"{tx.tx_hash}: {tx.method} - {tx.value}") + ``` """ from human_protocol_sdk.gql.transaction import get_transactions_query diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py index c9c5b9034e..168d17ebb0 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/utils.py @@ -3,7 +3,7 @@ import os import time import re -from typing import Tuple, Optional +from typing import Tuple, Optional, Any, Dict, Type from dataclasses import dataclass import requests @@ -34,20 +34,40 @@ @dataclass class SubgraphOptions: - """Configuration for subgraph logic.""" + """Configuration options for subgraph queries with retry logic and indexer routing. + + Attributes: + max_retries (Optional[int]): Maximum number of retry attempts for failed queries. Must be paired with base_delay. + base_delay (Optional[int]): Base delay in milliseconds between retry attempts. Must be paired with max_retries. + indexer_id (Optional[str]): Specific indexer ID to route requests to (requires SUBGRAPH_API_KEY environment variable). + """ max_retries: Optional[int] = None - base_delay: Optional[int] = None # milliseconds + base_delay: Optional[int] = None indexer_id: Optional[str] = None def is_indexer_error(error: Exception) -> bool: - """ - Check if an error indicates that the indexer is down or not synced. - This function specifically checks for "bad indexers" errors from The Graph. + """Check if an error indicates that The Graph indexer is down or not synced. + + This function inspects error responses from The Graph API to detect "bad indexers" + messages that indicate infrastructure issues rather than query problems. + + Args: + error (Exception): The exception to check. - :param error: The error to check - :return: True if the error indicates indexer issues + Returns: + True if the error indicates indexer issues, False otherwise. + + Example: + ```python + try: + data = custom_gql_fetch(network, query) + except Exception as e: + if is_indexer_error(e): + # Retry with different indexer + pass + ``` """ if not error: return False @@ -75,21 +95,44 @@ def is_indexer_error(error: Exception) -> bool: def custom_gql_fetch( - network: dict, + network: Dict[str, Any], query: str, - params: dict = None, + params: Optional[Dict[str, Any]] = None, options: Optional[SubgraphOptions] = None, -): - """Fetch data from the subgraph with optional logic. - - :param network: Network configuration dictionary - :param query: GraphQL query string - :param params: Query parameters - :param options: Optional subgraph configuration - - :return: JSON response from the subgraph - - :raise Exception: If the subgraph query fails +) -> Dict[str, Any]: + """Fetch data from the subgraph with optional retry logic and indexer routing. + + Args: + network (Dict[str, Any]): Network configuration dictionary containing subgraph URLs. + query (str): GraphQL query string to execute. + params (Optional[Dict[str, Any]]): Optional query parameters/variables dictionary. + options (Optional[SubgraphOptions]): Optional subgraph configuration for retries and indexer selection. + + Returns: + JSON response from the subgraph containing the query results. + + Raises: + ValueError: If retry configuration is incomplete or indexer routing requires missing API key. + Exception: If the subgraph query fails after all retry attempts. + + Example: + ```python + from human_protocol_sdk.constants import NETWORKS, ChainId + from human_protocol_sdk.utils import SubgraphOptions, custom_gql_fetch + + network = NETWORKS[ChainId.POLYGON_AMOY] + query = "{ escrows(first: 10) { id address } }" + + # Simple query + data = custom_gql_fetch(network, query) + + # With retry logic + data = custom_gql_fetch( + network, + query, + options=SubgraphOptions(max_retries=3, base_delay=1000) + ) + ``` """ subgraph_api_key = os.getenv("SUBGRAPH_API_KEY", "") @@ -130,11 +173,25 @@ def custom_gql_fetch( def _fetch_subgraph_data( - network: dict, + network: Dict[str, Any], query: str, - params: dict = None, + params: Optional[Dict[str, Any]] = None, indexer_id: Optional[str] = None, -): +) -> Dict[str, Any]: + """Internal function to fetch data from the subgraph API. + + Args: + network (Dict[str, Any]): Network configuration dictionary containing subgraph URLs. + query (str): GraphQL query string to execute. + params (Optional[Dict[str, Any]]): Optional query parameters/variables dictionary. + indexer_id (Optional[str]): Optional indexer ID to route the request to. + + Returns: + JSON response from the subgraph. + + Raises: + Exception: If the HTTP request fails or returns a non-200 status code. + """ subgraph_api_key = os.getenv("SUBGRAPH_API_KEY", "") if subgraph_api_key: subgraph_url = network["subgraph_url_api_key"].replace( @@ -166,21 +223,43 @@ def _fetch_subgraph_data( def _attach_indexer_id(url: str, indexer_id: Optional[str]) -> str: + """Append indexer ID to the subgraph URL for routing. + + Args: + url: Base subgraph URL. + indexer_id: Optional indexer ID to append. + + Returns: + Modified URL with indexer routing path if indexer_id is provided, otherwise the original URL. + """ if not indexer_id: return url return f"{url}/indexers/id/{indexer_id}" -def get_hmt_balance(wallet_addr, token_addr, w3): - """Get HMT balance +def get_hmt_balance(wallet_addr: str, token_addr: str, w3: Web3) -> int: + """Get the HMT token balance for a wallet address. - :param wallet_addr: wallet address - :param token_addr: ERC-20 contract - :param w3: Web3 instance + Args: + wallet_addr (str): Wallet address to check balance for. + token_addr (str): ERC-20 token contract address. + w3 (Web3): Web3 instance connected to the network. - :return: HMT balance (wei) - """ + Returns: + HMT token balance in wei. + + Example: + ```python + from web3 import Web3 + w3 = Web3(Web3.HTTPProvider("https://polygon-rpc.com")) + balance = get_hmt_balance( + "0x1234567890123456789012345678901234567890", + "0xc748B2A084F8eFc47E086ccdDD9b7e67aEb571BF", + w3 + ) + ``` + """ abi = [ { "constant": True, @@ -197,12 +276,27 @@ def get_hmt_balance(wallet_addr, token_addr, w3): def parse_transfer_transaction( hmtoken_contract: Contract, tx_receipt: Optional[TxReceipt] ) -> Tuple[bool, Optional[int]]: - """Parse a transfer transaction receipt. + """Parse a transaction receipt to extract HMT transfer information. + + Args: + hmtoken_contract: The HMT token contract instance. + tx_receipt: Transaction receipt to parse, or None. - :param hmtoken_contract: The HMT token contract - :param tx_receipt: The transaction receipt + Returns: + A tuple containing: - :return: A tuple indicating if HMT was transferred and the transaction balance + - bool: True if HMT was successfully transferred, False otherwise. + - Optional[int]: The transfer amount in wei if successful, None otherwise. + + Example: + ```python + from web3 import Web3 + + tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) + transferred, amount = parse_transfer_transaction(hmt_contract, tx_receipt) + if transferred: + print(f"Transferred {amount} wei") + ``` """ hmt_transferred = False tx_balance = None @@ -220,23 +314,37 @@ def parse_transfer_transaction( return hmt_transferred and tx_balance is not None, tx_balance -def get_contract_interface(contract_entrypoint): - """Retrieve the contract interface of a given contract. +def get_contract_interface(contract_entrypoint: str) -> Dict[str, Any]: + """Retrieve the contract ABI and interface from a compiled artifact file. - :param contract_entrypoint: the entrypoint of the JSON. + Args: + contract_entrypoint (str): File path to the contract JSON artifact. - :return: The contract interface containing the contract abi. - """ + Returns: + Contract interface dictionary containing the ABI and other metadata. + Example: + ```python + interface = get_contract_interface("artifacts/contracts/MyContract.sol/MyContract.json") + abi = interface["abi"] + ``` + """ with open(contract_entrypoint) as f: contract_interface = json.load(f) return contract_interface -def get_erc20_interface(): - """Retrieve the ERC20 interface. +def get_erc20_interface() -> Dict[str, Any]: + """Retrieve the standard ERC20 token contract interface. + + Returns: + The ERC20 contract interface containing the ABI. - :return: The ERC20 interface of smart contract. + Example: + ```python + erc20_interface = get_erc20_interface() + token_contract = w3.eth.contract(address=token_address, abi=erc20_interface["abi"]) + ``` """ return get_contract_interface( @@ -246,11 +354,17 @@ def get_erc20_interface(): ) -def get_factory_interface(): - """Retrieve the EscrowFactory interface. +def get_factory_interface() -> Dict[str, Any]: + """Retrieve the EscrowFactory contract interface. - :return: The EscrowFactory interface of smart contract. + Returns: + The EscrowFactory contract interface containing the ABI. + Example: + ```python + factory_interface = get_factory_interface() + factory_contract = w3.eth.contract(address=factory_address, abi=factory_interface["abi"]) + ``` """ return get_contract_interface( @@ -258,11 +372,17 @@ def get_factory_interface(): ) -def get_staking_interface(): - """Retrieve the Staking interface. +def get_staking_interface() -> Dict[str, Any]: + """Retrieve the Staking contract interface. - :return: The Staking interface of smart contract. + Returns: + The Staking contract interface containing the ABI. + Example: + ```python + staking_interface = get_staking_interface() + staking_contract = w3.eth.contract(address=staking_address, abi=staking_interface["abi"]) + ``` """ return get_contract_interface( @@ -270,11 +390,17 @@ def get_staking_interface(): ) -def get_escrow_interface(): - """Retrieve the RewardPool interface. +def get_escrow_interface() -> Dict[str, Any]: + """Retrieve the Escrow contract interface. - :return: The RewardPool interface of smart contract. + Returns: + The Escrow contract interface containing the ABI. + Example: + ```python + escrow_interface = get_escrow_interface() + escrow_contract = w3.eth.contract(address=escrow_address, abi=escrow_interface["abi"]) + ``` """ return get_contract_interface( @@ -282,11 +408,17 @@ def get_escrow_interface(): ) -def get_kvstore_interface(): - """Retrieve the KVStore interface. +def get_kvstore_interface() -> Dict[str, Any]: + """Retrieve the KVStore contract interface. - :return: The KVStore interface of smart contract. + Returns: + The KVStore contract interface containing the ABI. + Example: + ```python + kvstore_interface = get_kvstore_interface() + kvstore_contract = w3.eth.contract(address=kvstore_address, abi=kvstore_interface["abi"]) + ``` """ return get_contract_interface( @@ -294,25 +426,30 @@ def get_kvstore_interface(): ) -def handle_error(e, exception_class): - """ - Handles and translates errors raised during contract transactions. +def handle_error(e: Exception, exception_class: Type[Exception]) -> None: + """Handle and translate errors raised during contract transactions. This function captures exceptions (especially ContractLogicError from web3.py), - extracts meaningful revert reasons if present, logs unexpected errors, and raises + extracts meaningful revert reasons when present, logs unexpected errors, and raises a custom exception with a clear message for SDK users. - :param e: The exception object raised during a transaction. - :param exception_class: The custom exception class to raise (e.g., EscrowClientError). + Args: + e (Exception): The exception object raised during a transaction. + exception_class (Type[Exception]): The custom exception class to raise (e.g., EscrowClientError). + + Raises: + exception_class: Always raises the provided exception class with a formatted error message. - :raises exception_class: With a detailed error message, including contract revert reasons if available. + Example: + ```python + from human_protocol_sdk.escrow import EscrowClientError - :example: try: tx_hash = contract.functions.someMethod(...).transact() w3.eth.wait_for_transaction_receipt(tx_hash) except Exception as e: handle_error(e, EscrowClientError) + ``` """ def extract_reason(msg): @@ -349,13 +486,27 @@ def extract_reason(msg): def validate_url(url: str) -> bool: - """Validates the given URL. + """Validate whether a string is a properly formatted URL. + + This function supports both standard URLs and Docker network URLs that may + not be recognized by strict validators. + + Args: + url: URL string to validate (e.g., "https://example.com" or "http://localhost:8080"). + + Returns: + True if the URL is valid, False otherwise. - :param url: Public or private URL address + Raises: + ValidationFailure: If the URL format is invalid according to the validators library. - :return: True if URL is valid, False otherwise + Example: + ```python + from human_protocol_sdk.utils import validate_url - :raise ValidationFailure: If the URL is invalid + if validate_url("https://example.com"): + print("Valid URL") + ``` """ # validators.url tracks docker network URL as invalid @@ -384,9 +535,21 @@ def validate_url(url: str) -> bool: def validate_json(data: str) -> bool: - """Validates if the given string is a valid JSON. - :param data: String to validate - :return: True if the string is a valid JSON, False otherwise + """Validate whether a string contains valid JSON data. + + Args: + data: String to validate as JSON. + + Returns: + True if the string is valid JSON, False otherwise. + + Example: + ```python + from human_protocol_sdk.utils import validate_json + + if validate_json('{"key": "value"}'): + print("Valid JSON") + ``` """ try: json.loads(data) diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/worker/worker_utils.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/worker/worker_utils.py index 1bdab5ca14..27de33976a 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/worker/worker_utils.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/worker/worker_utils.py @@ -1,3 +1,18 @@ +"""Utility helpers for worker-related queries. + +Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.worker import WorkerUtils, WorkerFilter + + workers = WorkerUtils.get_workers( + WorkerFilter(chain_id=ChainId.POLYGON_AMOY) + ) + for worker in workers: + print(f"{worker.address}: {worker.total_amount_received}") + ``` +""" + import logging from typing import List, Optional @@ -11,14 +26,21 @@ class WorkerUtilsError(Exception): - """ - Raised when an error occurs when getting data from subgraph. - """ + """Exception raised when errors occur during worker data retrieval operations.""" pass class WorkerData: + """Represents worker information retrieved from the subgraph. + + Attributes: + id (str): Unique worker identifier. + address (str): Worker's Ethereum address. + total_amount_received (int): Total amount of HMT tokens received by the worker. + payout_count (int): Number of payouts the worker has received. + """ + def __init__( self, id: str, @@ -26,15 +48,6 @@ def __init__( total_amount_received: str, payout_count: str, ): - """ - Initializes a WorkerData instance. - - :param id: Worker ID - :param address: Worker address - :param total_amount_received: Total amount received by the worker - :param payout_count: Number of payouts received by the worker - """ - self.id = id self.address = address self.total_amount_received = int(total_amount_received) @@ -42,8 +55,10 @@ def __init__( class WorkerUtils: - """ - A utility class that provides additional worker-related functionalities. + """Utility class providing worker-related query and data retrieval functions. + + This class offers static methods to fetch worker data from the Human Protocol + subgraph, including filtered worker lists and individual worker details. """ @staticmethod @@ -51,12 +66,44 @@ def get_workers( filter: WorkerFilter, options: Optional[SubgraphOptions] = None, ) -> List[WorkerData]: - """Get workers data of the protocol. + """Retrieve a list of workers matching the provided filter criteria. + + Queries the subgraph for workers based on the specified parameters including + address filters, ordering preferences, and pagination. + + Args: + filter (WorkerFilter): Filter parameters including chain ID, worker address, + ordering, and pagination options. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests + such as custom endpoints or timeout settings. + + Returns: + A list of worker records matching the filter criteria. + Returns an empty list if no matches are found. - :param filter: Worker filter - :param options: Optional config for subgraph requests + Raises: + WorkerUtilsError: If the chain ID is not supported. - :return: List of workers data + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.worker import WorkerUtils, WorkerFilter + + # Get all workers + workers = WorkerUtils.get_workers( + WorkerFilter(chain_id=ChainId.POLYGON_AMOY) + ) + for worker in workers: + print(f"{worker.address}: {worker.total_amount_received} HMT") + + # Get specific worker + workers = WorkerUtils.get_workers( + WorkerFilter( + chain_id=ChainId.POLYGON_AMOY, + worker_address="0x1234567890123456789012345678901234567890", + ) + ) + ``` """ from human_protocol_sdk.gql.worker import get_workers_query @@ -107,13 +154,35 @@ def get_worker( worker_address: str, options: Optional[SubgraphOptions] = None, ) -> Optional[WorkerData]: - """Gets the worker details. + """Retrieve a single worker by their address. + + Fetches detailed information about a specific worker from the subgraph, + including their total earnings and payout history. + + Args: + chain_id (ChainId): Network where the worker has participated. + worker_address (str): Ethereum address of the worker. + options (Optional[SubgraphOptions]): Optional configuration for subgraph requests. - :param chain_id: Network in which the worker exists - :param worker_address: Address of the worker - :param options: Optional config for subgraph requests + Returns: + Worker data if found, otherwise ``None``. - :return: Worker data if exists, otherwise None + Raises: + WorkerUtilsError: If the chain ID is not supported or the worker address is invalid. + + Example: + ```python + from human_protocol_sdk.constants import ChainId + from human_protocol_sdk.worker import WorkerUtils + + worker = WorkerUtils.get_worker( + ChainId.POLYGON_AMOY, + "0x1234567890123456789012345678901234567890", + ) + if worker: + print(f"Total received: {worker.total_amount_received} HMT") + print(f"Payout count: {worker.payout_count}") + ``` """ from human_protocol_sdk.gql.worker import get_worker_query @@ -123,7 +192,7 @@ def get_worker( raise WorkerUtilsError("Unsupported Chain ID") if not Web3.is_address(worker_address): - raise WorkerUtilsError(f"Invalid operator address: {worker_address}") + raise WorkerUtilsError(f"Invalid worker address: {worker_address}") network = NETWORKS[chain_id] worker_data = custom_gql_fetch( diff --git a/packages/sdk/typescript/human-protocol-sdk/.gitignore b/packages/sdk/typescript/human-protocol-sdk/.gitignore index f87fcba870..4d3fb3fcc4 100644 --- a/packages/sdk/typescript/human-protocol-sdk/.gitignore +++ b/packages/sdk/typescript/human-protocol-sdk/.gitignore @@ -7,5 +7,5 @@ dist # Logs logs -#Docs -docs \ No newline at end of file +docs +!docs/index.md \ No newline at end of file diff --git a/packages/sdk/typescript/human-protocol-sdk/docs/index.md b/packages/sdk/typescript/human-protocol-sdk/docs/index.md new file mode 100644 index 0000000000..2fbde867d1 --- /dev/null +++ b/packages/sdk/typescript/human-protocol-sdk/docs/index.md @@ -0,0 +1,294 @@ +# HUMAN Protocol TypeScript SDK + +The **HUMAN Protocol TypeScript SDK** provides a comprehensive, type-safe interface for interacting with HUMAN Protocol smart contracts and off-chain services. It enables developers to build decentralized job marketplaces, data labeling platforms, and other human-in-the-loop applications on blockchain networks. + +## Overview + +HUMAN Protocol is a decentralized infrastructure for coordinating human work at scale. The TypeScript SDK simplifies integration by providing high-level abstractions for: + +- **Escrow Management**: Create, fund, and manage escrow contracts for job distribution +- **Staking Operations**: Stake HMT tokens and manage operator allocations +- **On-chain Storage**: Store and retrieve configuration data using KVStore +- **Operator Discovery**: Query and filter operators by role, reputation, and capabilities +- **Worker Analytics**: Track worker performance and payout history +- **Statistics**: Access protocol-wide metrics and analytics +- **Encryption**: Secure message encryption using PGP for private communications + +!!! info "Subgraph access and rate limits" + The SDK calls public subgraph endpoints by default. Unauthenticated requests are rate-limited and may return errors. For higher limits, use your own [API key](https://thegraph.com/docs/it/subgraphs/querying/managing-api-keys/). + +## Key Features + +### Smart Contract Clients + +- **EscrowClient**: Full lifecycle management of escrow contracts + - Create, fund, and configure escrows + - Bulk payout distribution with string-based IDs + - Store and verify results with hash validation + - Cancel, request cancellation, and refund mechanisms + - Withdraw additional tokens +- **StakingClient**: Manage HMT token staking + - Stake, unstake, and withdraw operations + - Slash malicious operators + - Query staking information +- **KVStoreClient**: On-chain key-value storage + - Store operator configuration + - Manage URLs with automatic hash verification + - Retrieve public keys and metadata + +### Subgraph Utilities + +- **EscrowUtils**: Query escrow data, status events, payouts, and cancellation refunds +- **OperatorUtils**: Discover operators by role, reputation network, and rewards +- **StakingUtils**: Access staker information and statistics +- **WorkerUtils**: Query worker statistics and payout history +- **StatisticsUtils**: Retrieve protocol statistics and HMT token metrics +- **TransactionUtils**: Query on-chain transactions with advanced filters + +### Developer Tools + +- **EncryptionUtils**: PGP-based message encryption, signing, and key generation +- **Type Safety**: Full TypeScript support with comprehensive type definitions +- **Error Handling**: Descriptive exceptions with clear error messages +- **Flexible Filters**: Query builders for subgraph data with pagination and ordering +- **Multi-network Support**: Built-in configurations for multiple chains + +## Installation + +### npm + +```bash +npm install @human-protocol/sdk +``` + +### yarn + +```bash +yarn add @human-protocol/sdk +``` + +!!! warning "Keep ethers in sync" + The SDK is built against a specific `ethers` major/minor (currently `6.15.x`). Pin the same major/minor in your app. Mixing different minors (e.g., `6.16.x` with the SDK) can trigger errors. + +## Quick Start + +### Read-Only Operations + +Query escrow data without a signer: + +```typescript +import { EscrowUtils, ChainId, EscrowStatus } from '@human-protocol/sdk'; + +// Get escrows from the subgraph +const escrows = await EscrowUtils.getEscrows({ + chainId: ChainId.POLYGON_AMOY, + status: EscrowStatus.Pending, + first: 10, +}); + +for (const escrow of escrows) { + console.log(`Escrow: ${escrow.address}`); + console.log(`Balance: ${escrow.balance}`); + console.log(`Status: ${escrow.status}`); +} +``` + +### Write Operations + +Create and fund an escrow with a signer: + +```typescript +import { EscrowClient } from '@human-protocol/sdk'; +import { Wallet, JsonRpcProvider, parseUnits } from 'ethers'; + +// Initialize provider and signer +const provider = new JsonRpcProvider('https://polygon-amoy-rpc.com'); +const signer = new Wallet('YOUR_PRIVATE_KEY', provider); + +// Create escrow client +const escrowClient = await EscrowClient.build(signer); + +// Create escrow configuration +const escrowConfig = { + recordingOracle: '0x...', + reputationOracle: '0x...', + exchangeOracle: '0x...', + recordingOracleFee: 10n, + reputationOracleFee: 10n, + exchangeOracleFee: 10n, + manifest: 'https://example.com/manifest.json', + manifestHash: 'manifest_hash', +}; + +// Create and setup escrow +const escrowAddress = await escrowClient.createFundAndSetupEscrow( + '0x...', // token address + parseUnits('100', 18), + 'job-requester-123', + escrowConfig +); + +console.log(`Created escrow: ${escrowAddress}`); +``` + +### Query Statistics + +Access protocol-wide statistics: + +```typescript +import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; + +// Get network data +const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + +// Get escrow statistics +const stats = await StatisticsUtils.getEscrowStatistics(networkData); +console.log(`Total escrows: ${stats.totalEscrows}`); + +// Get HMT token statistics +const hmtStats = await StatisticsUtils.getHMTStatistics(networkData); +console.log(`Total holders: ${hmtStats.totalHolders}`); +console.log(`Total transfers: ${hmtStats.totalTransferCount}`); +``` + +### Operator Discovery + +Find operators by role and reputation: + +```typescript +import { OperatorUtils, ChainId } from '@human-protocol/sdk'; + +// Find recording oracles +const operators = await OperatorUtils.getOperators({ + chainId: ChainId.POLYGON_AMOY, + roles: ['Recording Oracle'], + first: 10, +}); + +for (const operator of operators) { + console.log(`Operator: ${operator.address}`); + console.log(`Role: ${operator.role}`); + console.log(`Staked: ${operator.stakedAmount}`); +} +``` + +### Encryption + +Encrypt and decrypt messages using PGP: + +```typescript +import { Encryption, EncryptionUtils } from '@human-protocol/sdk'; + +// Generate key pair +const keyPair = await EncryptionUtils.generateKeyPair( + 'Alice', + 'alice@example.com', + 'passphrase123' +); + +// Initialize encryption with private key +const encryption = await Encryption.build( + keyPair.privateKey, + 'passphrase123' +); + +// Sign and encrypt a message +const publicKeys = [keyPair.publicKey, 'OTHER_PUBLIC_KEY']; +const encrypted = await encryption.signAndEncrypt('Hello, HUMAN!', publicKeys); + +// Decrypt and verify +const decrypted = await encryption.decrypt(encrypted, keyPair.publicKey); +console.log(new TextDecoder().decode(decrypted)); +``` + +## Supported Networks + +The SDK supports multiple blockchain networks: + +- **Mainnet**: Ethereum, Polygon, BSC +- **Testnets**: Sepolia, Polygon Amoy, BSC Testnet +- **Local Development**: Localhost (Hardhat/Ganache) + +Network configurations are automatically loaded based on the provider's chain ID. + +## Architecture + +The SDK is organized into several modules: + +- **`escrow`**: Escrow contract client and utilities +- **`staking`**: Staking contract client and utilities +- **`kvstore`**: Key-value store client and utilities +- **`operator`**: Operator discovery and management utilities +- **`worker`**: Worker statistics utilities +- **`statistics`**: Protocol statistics utilities (instance-based and static methods) +- **`transaction`**: Transaction query utilities +- **`encryption`**: PGP encryption helpers (instance-based and static methods) +- **`constants`**: Network configurations and enums +- **`types`**: TypeScript type definitions +- **`interfaces`**: Interface definitions for data structures + +## Usage Patterns + +### Client Classes vs Utility Classes + +The SDK provides two patterns for interacting with the protocol: + +**Client Classes** (require Signer/Provider): +- `EscrowClient` +- `StakingClient` +- `KVStoreClient` + +```typescript +const client = await EscrowClient.build(signerOrProvider); +const balance = await client.getBalance(escrowAddress); +``` + +**Utility Classes** (static methods, no initialization): +- `EscrowUtils` +- `StakingUtils` +- `KVStoreUtils` +- `OperatorUtils` +- `WorkerUtils` +- `StatisticsUtils` +- `TransactionUtils` + +```typescript +const escrows = await EscrowUtils.getEscrows(filter); +const operators = await OperatorUtils.getOperators(filter); +``` + +### Subgraph Configuration + +Control subgraph requests with optional parameters: + +```typescript +const escrows = await EscrowUtils.getEscrows( + filter, + { + maxRetries: 3, + baseDelay: 1000, + indexerId: 'specific-indexer-id' + } +); +``` + +Environment variable for API key: + +```bash +export SUBGRAPH_API_KEY="your-api-key" +``` + +## Requirements + +- Node.js 16.0 or higher +- TypeScript 4.7+ (for development) +- ethers.js 6.0+ +- Access to an Ethereum-compatible RPC endpoint +- (Optional) Private key for transaction signing + +## Resources + +- [GitHub Repository](https://github.com/humanprotocol/human-protocol) +- [HUMAN Protocol Documentation](https://docs.humanprotocol.org/) +- [Discord Community](https://discord.gg/humanprotocol) +- [Website](https://www.humanprotocol.org/) diff --git a/packages/sdk/typescript/human-protocol-sdk/package.json b/packages/sdk/typescript/human-protocol-sdk/package.json index 67a4a66f3c..064997acae 100644 --- a/packages/sdk/typescript/human-protocol-sdk/package.json +++ b/packages/sdk/typescript/human-protocol-sdk/package.json @@ -10,9 +10,9 @@ "types": "dist/index.d.ts", "scripts": { "clean": "tsc --build --clean && rm -rf ./dist", - "clean:doc": "rm -rf ../../../../docs/sdk/typescript/", "build": "yarn clean && tsc --build", - "build:doc": "yarn clean:doc && typedoc --plugin typedoc-plugin-markdown --out ../../../../docs/sdk/typescript/", + "docs:post": "ts-node scripts/postprocess-docs.ts", + "build:doc": "typedoc && yarn docs:post", "test": "vitest -u", "lint": "eslint .", "lint:fix": "eslint . --fix", @@ -54,27 +54,11 @@ "eslint": "^9.39.1", "eslint-plugin-jest": "^28.9.0", "eslint-plugin-prettier": "^5.2.1", + "glob": "^13.0.0", "prettier": "^3.7.4", "ts-node": "^10.9.2", - "typedoc": "^0.28.7", - "typedoc-plugin-markdown": "^4.2.3", + "typedoc": "^0.28.15", + "typedoc-plugin-markdown": "^4.9.0", "typescript": "^5.8.3" - }, - "typedocOptions": { - "entryPoints": [ - "./src/base.ts", - "./src/encryption.ts", - "./src/escrow.ts", - "./src/kvstore.ts", - "./src/operator.ts", - "./src/staking.ts", - "./src/storage.ts", - "./src/statistics.ts", - "./src/transaction.ts", - "./src/enums.ts", - "./src/graphql/types.ts", - "./src/interfaces.ts", - "./src/types.ts" - ] } } diff --git a/packages/sdk/typescript/human-protocol-sdk/scripts/postprocess-docs.ts b/packages/sdk/typescript/human-protocol-sdk/scripts/postprocess-docs.ts new file mode 100644 index 0000000000..daeb65972e --- /dev/null +++ b/packages/sdk/typescript/human-protocol-sdk/scripts/postprocess-docs.ts @@ -0,0 +1,457 @@ +import { readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { globSync } from 'glob'; +import { PathOrFileDescriptor } from 'fs'; + +const ROOT = 'docs'; // adjust if needed + +function processFile(path: PathOrFileDescriptor) { + const original = readFileSync(path, 'utf8'); + let text = original; + + // First pass: keep original overload structure + text = collapseOverloadedMethods(text); + + const lines = text.split('\n'); + const out: string[] = []; + + let i = 0; + + while (i < lines.length) { + let line = lines[i]; + + // ---------- Handle a single Call Signature block as a unit ---------- + if (/^####\s+Call Signature/i.test(line)) { + const section: string[] = []; + // capture this call signature block until next call signature or next method heading + while (i < lines.length) { + const cur = lines[i]; + if (section.length > 0 && /^####\s+Call Signature/i.test(cur.trim())) { + break; + } + if (section.length > 0 && /^###\s+/.test(cur)) { + break; + } + section.push(cur); + i++; + } + out.push(...processCallSignatureSection(section)); + continue; + } + + // ---------- Normalize 5# headings to 4# for consistency ---------- + if ( + /^#####\s+(Parameters|Returns|Throws|Example|Examples|Remarks)\b/.test( + line + ) + ) { + // rewrite in-place and re-process this line + lines[i] = line = line.replace(/^#####/, '####'); + } + + // ---------- Convert parameter tables to have #### Parameters heading and capture full table ---------- + if (line.trim().match(/^\|\s*Parameter\s*\|\s*Type/i)) { + // Check if previous non-empty line is already "#### Parameters" + let lookBack = out.length - 1; + while (lookBack >= 0 && out[lookBack].trim() === '') lookBack--; + + if (lookBack < 0 || !out[lookBack].startsWith('#### Parameters')) { + // Remove trailing blanks then add heading + while (out.length > 0 && out[out.length - 1].trim() === '') out.pop(); + out.push(''); + out.push('#### Parameters'); + out.push(''); + } + + // Emit the whole table block: header + following rows + while (i < lines.length && lines[i].trim().startsWith('|')) { + out.push(lines[i]); + i++; + } + out.push(''); + continue; + } + + // ---------- THROWS: normalize into a single table and merge consecutive headings (non-overload context) ---------- + if (line.startsWith('#### Throws')) { + type Row = { type: string; desc: string }; + const rows: Row[] = []; + + const pushLineAsRow = (raw: string) => { + const cleaned = raw.trim().replace(/^-\s*/, ''); + const m = cleaned.match(/^`?([^`\s|]+)`?\s*(.*)$/); + if (m) { + rows.push({ type: m[1].trim(), desc: (m[2] || '').trim() }); + } else if (cleaned) { + rows.push({ type: '-', desc: cleaned }); + } + }; + + // consume one or more consecutive "#### Throws" sections + while (i < lines.length && lines[i].startsWith('#### Throws')) { + i++; // skip heading + + // skip blank lines + while (i < lines.length && lines[i].trim() === '') i++; + + if (i >= lines.length) break; + + // if table-form throws, parse all rows + if (lines[i].trim().startsWith('|')) { + const table: string[] = []; + while (i < lines.length && lines[i].trim().startsWith('|')) { + const l = lines[i].trim(); + table.push(l); + i++; + } + for (const r of table) { + const cells = r.split('|').map((c) => c.trim()); + if ( + cells.length >= 4 && + cells[1] && + cells[2] && + !/^(-{2,}|Type)$/i.test(cells[1]) && + !/^(-{2,}|Description)$/i.test(cells[2]) + ) { + const typeCell = cells[1].replace(/`/g, '').trim(); + const descCell = cells[2].trim(); + rows.push({ type: typeCell || '-', desc: descCell || '-' }); + } + } + } else { + // freeform lines until next heading or blank line + while ( + i < lines.length && + lines[i].trim() !== '' && + !/^### /.test(lines[i]) && + !/^#### /.test(lines[i]) && + !/^##### /.test(lines[i]) + ) { + pushLineAsRow(lines[i]); + i++; + } + } + + // skip blank lines between throws blocks + while (i < lines.length && lines[i].trim() === '') i++; + } + + // emit one normalized table + out.push('#### Throws', ''); + out.push('| Type | Description |'); + out.push('|------|-------------|'); + for (const r of rows) { + out.push(`| \`${r.type || '-'}\` | ${r.desc || '-'} |`); + } + out.push(''); + continue; + } + + // ---------- RETURNS: normalize into a table (after heading normalization) ---------- + if (line.startsWith('#### Returns')) { + i++; // skip heading + + // skip blank lines + while (i < lines.length && lines[i].trim() === '') i++; + + if (i >= lines.length) { + out.push('#### Returns'); + break; + } + + // type line (e.g. `Promise`\<`void`\> or `Promise`) + const typeLine = lines[i].trim(); + i++; + + // skip blank lines + while (i < lines.length && lines[i].trim() === '') i++; + + // description lines until blank or next heading + const descParts: string[] = []; + while ( + i < lines.length && + lines[i].trim() !== '' && + !/^###? /.test(lines[i]) && + !/^#### /.test(lines[i]) && + !/^##### /.test(lines[i]) + ) { + descParts.push(lines[i].trim()); + i++; + } + + // clean type: remove backticks and backslash escapes + let rawType = typeLine + .replace(/`/g, '') + .replace(/\\/g, '>'); + rawType = rawType.trim(); + + // strip Promise<...> wrapper + const type = rawType.replace(/^Promise\s*<\s*([^>]+)\s*>$/i, '$1').trim(); + + const desc = descParts.join(' '); + + out.push('#### Returns', ''); + out.push('| Type | Description |'); + out.push('|------|-------------|'); + out.push(`| \`${type}\` | ${desc || '-'} |`); + out.push(''); + + // skip any trailing blank lines we already consumed + while (i < lines.length && lines[i].trim() === '') i++; + + continue; + } + + // ---------- Handle orphan Param sections (from overloads) ---------- + if (line.startsWith('#### Param')) { + // Skip orphan param lines that appear before method signatures + i++; + while (i < lines.length && lines[i].trim() === '') i++; + continue; + } + + // default: copy line + out.push(line); + i++; + } + + // second pass: transform Examples into admonitions + text = out.join('\n'); + text = transformExamples(text); + + writeFileSync(path, text); +} + +// ---------- Process a single Call Signature block ---------- +function processCallSignatureSection(section: string[]): string[] { + const t = (s: string) => s.trim(); + // normalize 5# to 4# inside the section + section = section.map((l) => + l.replace( + /^#####\s+(Parameters|Returns|Throws|Example|Examples|Remarks)\b/, + '#### $1' + ) + ); + + const out: string[] = []; + const throwRows: { type: string; desc: string }[] = []; + let firstThrowsOutIdx: number | null = null; + + const pushLineAsThrowRow = (raw: string) => { + const cleaned = raw.trim().replace(/^-\s*/, ''); + const m = cleaned.match(/^`?([^`\s|]+)`?\s*(.*)$/); + if (m) { + throwRows.push({ type: m[1].trim(), desc: (m[2] || '').trim() }); + } else if (cleaned) { + throwRows.push({ type: '-', desc: cleaned }); + } + }; + + let i = 0; + while (i < section.length) { + const line = section[i]; + + // Parameter table without heading: add heading, then copy table + if (t(line).match(/^\|\s*Parameter\s*\|\s*Type/i)) { + // ensure "#### Parameters" before + let lookBack = out.length - 1; + while (lookBack >= 0 && out[lookBack].trim() === '') lookBack--; + if (lookBack < 0 || !out[lookBack].startsWith('#### Parameters')) { + while (out.length > 0 && out[out.length - 1].trim() === '') out.pop(); + out.push(''); + out.push('#### Parameters'); + out.push(''); + } + // emit full table + while (i < section.length && t(section[i]).startsWith('|')) { + out.push(section[i]); + i++; + } + out.push(''); + continue; + } + + // Returns: normalize into a table + if (t(line).startsWith('#### Returns')) { + i++; // skip heading + while (i < section.length && t(section[i]) === '') i++; + if (i >= section.length) { + out.push('#### Returns'); + break; + } + const typeLine = t(section[i] || ''); + i++; + while (i < section.length && t(section[i]) === '') i++; + + const descParts: string[] = []; + while ( + i < section.length && + t(section[i]) !== '' && + !/^#### /.test(t(section[i])) && + !/^### /.test(t(section[i])) + ) { + descParts.push(t(section[i])); + i++; + } + + let rawType = typeLine + .replace(/`/g, '') + .replace(/\\/g, '>'); + rawType = rawType.trim(); + const type = rawType.replace(/^Promise\s*<\s*([^>]+)\s*>$/i, '$1').trim(); + const desc = descParts.join(' '); + + out.push('#### Returns', ''); + out.push('| Type | Description |'); + out.push('|------|-------------|'); + out.push(`| \`${type}\` | ${desc || '-'} |`); + out.push(''); + while (i < section.length && t(section[i]) === '') i++; + continue; + } + + // Throws: collect rows, defer emission; skip original throws blocks + if (t(line).startsWith('#### Throws')) { + if (firstThrowsOutIdx === null) firstThrowsOutIdx = out.length; + i++; // skip heading + while (i < section.length && t(section[i]) === '') i++; + if (i >= section.length) break; + + if (t(section[i]).startsWith('|')) { + // table form + const table: string[] = []; + while (i < section.length && t(section[i]).startsWith('|')) { + table.push(section[i].trim()); + i++; + } + for (const r of table) { + const cells = r.split('|').map((c) => c.trim()); + if ( + cells.length >= 4 && + cells[1] && + cells[2] && + !/^(-{2,}|Type)$/i.test(cells[1]) && + !/^(-{2,}|Description)$/i.test(cells[2]) + ) { + const typeCell = cells[1].replace(/`/g, '').trim(); + const descCell = cells[2].trim(); + throwRows.push({ type: typeCell || '-', desc: descCell || '-' }); + } + } + } else { + // freeform + while ( + i < section.length && + t(section[i]) !== '' && + !/^#### /.test(t(section[i])) && + !/^### /.test(t(section[i])) + ) { + pushLineAsThrowRow(section[i]); + i++; + } + } + // skip blank lines after each throws block + while (i < section.length && t(section[i]) === '') i++; + continue; + } + + // Default: copy line + out.push(line); + i++; + } + + // Insert merged Throws table at the first encountered position (or append at end if not found) + if (throwRows.length > 0) { + const block: string[] = []; + block.push('#### Throws', ''); + block.push('| Type | Description |'); + block.push('|------|-------------|'); + for (const r of throwRows) { + block.push(`| \`${r.type || '-'}\` | ${r.desc || '-'} |`); + } + block.push(''); + + const insertAt = firstThrowsOutIdx ?? out.length; + out.splice(insertAt, 0, ...block); + } + + return out; +} + +// ---------- EXAMPLES -> admonition ---------- +function transformExamples(text: string): string { + const lines = text.split('\n'); + const out: string[] = []; + let i = 0; + + while (i < lines.length) { + const line = lines[i]; + + // Match "#### Example" or "#### Examples" + if (/^####\s+Examples?/.test(line)) { + i++; // skip heading + + // Skip blank lines + while (i < lines.length && lines[i].trim() === '') i++; + + // If next line is not a code fence, leave it alone + if (i >= lines.length || !lines[i].trim().startsWith('```')) { + out.push('#### Example'); + continue; + } + + // Capture exactly one fenced code block + const code: string[] = []; + code.push(lines[i]); // opening ``` + i++; + + // Capture lines until closing ``` + while (i < lines.length && !lines[i].trim().startsWith('```')) { + code.push(lines[i]); + i++; + } + + // Capture final ``` + if (i < lines.length) { + code.push(lines[i]); + i++; + } + + // Emit MkDocs Material example block + out.push('???+ example "Example"', ''); + for (const l of code) out.push(' ' + l); // indent + out.push(''); + + continue; + } + + // Normalize 5# "##### Examples" to 4# earlier in processFile; also handle here just in case + if (/^#####\s+Examples?/.test(line)) { + out.push(line.replace(/^#####/, '####')); + i++; + continue; + } + + out.push(line); + i++; + } + + return out.join('\n'); +} + +// ---------- Collapse overloaded methods: no-op to keep Call Signature blocks ---------- +function collapseOverloadedMethods(text: string): string { + return text; +} + +// add runner to process all docs +function main() { + const files = globSync(join(ROOT, '**/*.md')); + for (const file of files) { + processFile(file); + } +} + +main(); diff --git a/packages/sdk/typescript/human-protocol-sdk/src/base.ts b/packages/sdk/typescript/human-protocol-sdk/src/base.ts index a0f3083da7..b9be0c077d 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/base.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/base.ts @@ -2,10 +2,9 @@ import { ContractRunner } from 'ethers'; import { NetworkData } from './types'; /** - * ## Introduction - * - * This class is used as a base class for other clients making on-chain calls. + * Base class for clients making on-chain calls. * + * This class provides common functionality for interacting with Ethereum contracts. */ export abstract class BaseEthersClient { protected runner: ContractRunner; @@ -14,8 +13,8 @@ export abstract class BaseEthersClient { /** * **BaseClient constructor** * - * @param {ContractRunner} runner The Signer or Provider object to interact with the Ethereum network - * @param {NetworkData} networkData The network information required to connect to the contracts + * @param runner - The Signer or Provider object to interact with the Ethereum network + * @param networkData - The network information required to connect to the contracts */ constructor(runner: ContractRunner, networkData: NetworkData) { this.networkData = networkData; diff --git a/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts b/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts index 38d1921f93..208f3b9513 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/encryption.ts @@ -4,8 +4,10 @@ import { IKeyPair } from './interfaces'; /** * Type representing the data type of a message. * It can be either a string or a Uint8Array. + * + * @public */ -type MessageDataType = string | Uint8Array; +export type MessageDataType = string | Uint8Array; function makeMessageDataBinary(message: MessageDataType): Uint8Array { if (typeof message === 'string') { @@ -16,44 +18,11 @@ function makeMessageDataBinary(message: MessageDataType): Uint8Array { } /** - * ## Introduction - * * Class for signing and decrypting messages. * * The algorithm includes the implementation of the [PGP encryption algorithm](https://github.com/openpgpjs/openpgpjs) multi-public key encryption on typescript, and uses the vanilla [ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) implementation Schnorr signature for signatures and [curve25519](https://en.wikipedia.org/wiki/Curve25519) for encryption. [Learn more](https://wiki.polkadot.network/docs/learn-cryptography). * - * To get an instance of this class, initialization is recommended using the static `build` method. - * - * ```ts - * static async build(privateKeyArmored: string, passphrase?: string): Promise - * ``` - * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Input parameters - * - * - `privateKeyArmored` - The encrypted private key in armored format. - * - `passphrase` - The passphrase for the private key. - * - * ## Code example - * - * ```ts - * import { Encryption } from '@human-protocol/sdk'; - * - * const privateKey = 'Armored_priv_key'; - * const passphrase = 'example_passphrase'; - * const encryption = await Encryption.build(privateKey, passphrase); - * ``` + * To get an instance of this class, initialization is recommended using the static [`build`](/ts/classes/Encryption/#build) method. */ export class Encryption { private privateKey: openpgp.PrivateKey; @@ -61,7 +30,7 @@ export class Encryption { /** * Constructor for the Encryption class. * - * @param {PrivateKey} privateKey - The private key. + * @param privateKey - The private key. */ constructor(privateKey: openpgp.PrivateKey) { this.privateKey = privateKey; @@ -70,9 +39,18 @@ export class Encryption { /** * Builds an Encryption instance by decrypting the private key from an encrypted private key and passphrase. * - * @param {string} privateKeyArmored - The encrypted private key in armored format. - * @param {string} passphrase - Optional: The passphrase for the private key. - * @returns {Promise} - The Encryption instance. + * @param privateKeyArmored - The encrypted private key in armored format. + * @param passphrase - The passphrase for the private key (optional). + * @returns The Encryption instance. + * + * @example + * ```ts + * import { Encryption } from '@human-protocol/sdk'; + * + * const privateKey = 'Armored_priv_key'; + * const passphrase = 'example_passphrase'; + * const encryption = await Encryption.build(privateKey, passphrase); + * ``` */ public static async build( privateKeyArmored: string, @@ -98,45 +76,18 @@ export class Encryption { /** * This function signs and encrypts a message using the private key used to initialize the client and the specified public keys. * - * @param {MessageDataType} message Message to sign and encrypt. - * @param {string[]} publicKeys Array of public keys to use for encryption. - * @returns {Promise} Message signed and encrypted. - * - * **Code example** + * @param message - Message to sign and encrypt. + * @param publicKeys - Array of public keys to use for encryption. + * @returns Message signed and encrypted. * + * @example * ```ts - * import { Encryption } from '@human-protocol/sdk'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const privateKey = 'Armored_priv_key'; - * const passphrase = 'example_passphrase'; - * const encryption = await Encryption.build(privateKey, passphrase); - * const publicKey1 = `-----BEGIN PGP PUBLIC KEY BLOCK----- - * xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v - * WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME - * CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF - * X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS - * CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 - * YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc - * UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv - * -----END PGP PUBLIC KEY BLOCK-----`; - * - * const publicKey2 = `-----BEGIN PGP PUBLIC KEY BLOCK----- - * xjMEZKQEMxYJKwYBBAHaRw8BAQdAG6h+E+6T/RV2tIHer3FP/jKThAyGcoVx - * FzhnP0hncPzNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME - * CwkHCAkQPIq5xLhlTYkDFQgKBBYAAgECGQECGwMCHgEWIQTcxtMgul/AeUvH - * bio8irnEuGVNiQAA/HsBANpfFkxNYixpsBk8LlaaCaPy5f1/cWNPgODM9uzo - * ciSTAQDtAYynu4dSJO9GbMuDuc0FaUHRWJK3mS6JkvedYL4oBM44BGSkBDMS - * CisGAQQBl1UBBQEBB0DWbEG7DMhkeSc8ZPzrH8XNSCqS3t9y/oQidFR+xN3Z - * bAMBCAfCeAQYFggAKgUCZKQEMwkQPIq5xLhlTYkCGwwWIQTcxtMgul/AeUvH - * bio8irnEuGVNiQAAqt8BAM/4Lw0RVOb0L5Ki9CyxO/6AKvRg4ra3Q3WR+duP - * s/88AQCDErzvn+SOX4s3gvZcM3Vr4wh4Q2syHV8Okgx8STYPDg===DsVk - * -----END PGP PUBLIC KEY BLOCK-----`; + * const publicKey1 = '-----BEGIN PGP PUBLIC KEY BLOCK-----...'; + * const publicKey2 = '-----BEGIN PGP PUBLIC KEY BLOCK-----...'; * * const publicKeys = [publicKey1, publicKey2]; * const resultMessage = await encryption.signAndEncrypt('message', publicKeys); + * console.log('Encrypted message:', resultMessage); * ``` */ public async signAndEncrypt( @@ -163,32 +114,17 @@ export class Encryption { /** * This function decrypts messages using the private key. In addition, the public key can be added for signature verification. * - * @param {string} message Message to decrypt. - * @param {string} publicKey Public key used to verify signature if needed. This is optional. - * @returns {Promise} Message decrypted. - * - * **Code example** + * @param message - Message to decrypt. + * @param publicKey - Public key used to verify signature if needed (optional). + * @returns Message decrypted. + * @throws Error If signature could not be verified when public key is provided * + * @example * ```ts - * import { Encryption } from '@human-protocol/sdk'; - * - * const privateKey = 'Armored_priv_key'; - * const passphrase = 'example_passphrase'; - * const encryption = await Encryption.build(privateKey, passphrase); - * - * const publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- - * xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v - * WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME - * CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF - * X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS - * CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 - * YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc - * UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv - * -----END PGP PUBLIC KEY BLOCK-----`; + * const publicKey = '-----BEGIN PGP PUBLIC KEY BLOCK-----...'; * - * const resultMessage = await encryption.decrypt('message'); + * const resultMessage = await encryption.decrypt('message', publicKey); + * console.log('Decrypted message:', resultMessage); * ``` */ public async decrypt( @@ -233,19 +169,13 @@ export class Encryption { /** * This function signs a message using the private key used to initialize the client. * - * @param {string} message Message to sign. - * @returns {Promise} Message signed. - * - * **Code example** + * @param message - Message to sign. + * @returns Message signed. * + * @example * ```ts - * import { Encryption } from '@human-protocol/sdk'; - * - * const privateKey = 'Armored_priv_key'; - * const passphrase = 'example_passphrase'; - * const encryption = await Encryption.build(privateKey, passphrase); - * * const resultMessage = await encryption.sign('message'); + * console.log('Signed message:', resultMessage); * ``` */ public async sign(message: string): Promise { @@ -263,56 +193,23 @@ export class Encryption { } /** - * ## Introduction - * * Utility class for encryption-related operations. - * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example - * - * ```ts - * import { EncryptionUtils } from '@human-protocol/sdk'; - * - * const keyPair = await EncryptionUtils.generateKeyPair('Human', 'human@hmt.ai'); - * ``` */ export class EncryptionUtils { /** * This function verifies the signature of a signed message using the public key. * - * @param {string} message Message to verify. - * @param {string} publicKey Public key to verify that the message was signed by a specific source. - * @returns {Promise} True if verified. False if not verified. - * - * **Code example** + * @param message - Message to verify. + * @param publicKey - Public key to verify that the message was signed by a specific source. + * @returns True if verified. False if not verified. * + * @example * ```ts * import { EncryptionUtils } from '@human-protocol/sdk'; * - * const publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- - * xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v - * WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME - * CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF - * X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS - * CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 - * YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc - * UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv - * -----END PGP PUBLIC KEY BLOCK-----`; - * + * const publicKey = '-----BEGIN PGP PUBLIC KEY BLOCK-----...'; * const result = await EncryptionUtils.verify('message', publicKey); + * console.log('Verification result:', result); * ``` */ public static async verify( @@ -337,15 +234,16 @@ export class EncryptionUtils { /** * This function gets signed data from a signed message. * - * @param {string} message Message. - * @returns {Promise} Signed data. - * - * **Code example** + * @param message - Message. + * @returns Signed data. + * @throws Error If data could not be extracted from the message * + * @example * ```ts * import { EncryptionUtils } from '@human-protocol/sdk'; * * const signedData = await EncryptionUtils.getSignedData('message'); + * console.log('Signed data:', signedData); * ``` */ public static async getSignedData(message: string): Promise { @@ -363,20 +261,20 @@ export class EncryptionUtils { /** * This function generates a key pair for encryption and decryption. * - * @param {string} name Name for the key pair. - * @param {string} email Email for the key pair. - * @param {string} passphrase Passphrase to encrypt the private key. Optional. - * @returns {Promise} Key pair generated. - * - * **Code example** + * @param name - Name for the key pair. + * @param email - Email for the key pair. + * @param passphrase - Passphrase to encrypt the private key (optional, defaults to empty string). + * @returns Key pair generated. * + * @example * ```ts * import { EncryptionUtils } from '@human-protocol/sdk'; * * const name = 'YOUR_NAME'; * const email = 'YOUR_EMAIL'; * const passphrase = 'YOUR_PASSPHRASE'; - * const result = await EncryptionUtils.generateKeyPair(name, email, passphrase); + * const keyPair = await EncryptionUtils.generateKeyPair(name, email, passphrase); + * console.log('Public key:', keyPair.publicKey); * ``` */ public static async generateKeyPair( @@ -404,41 +302,19 @@ export class EncryptionUtils { /** * This function encrypts a message using the specified public keys. * - * @param {MessageDataType} message Message to encrypt. - * @param {string[]} publicKeys Array of public keys to use for encryption. - * @returns {Promise} Message encrypted. - * - * **Code example** + * @param message - Message to encrypt. + * @param publicKeys - Array of public keys to use for encryption. + * @returns Message encrypted. * + * @example * ```ts * import { EncryptionUtils } from '@human-protocol/sdk'; * - * const publicKey1 = `-----BEGIN PGP PUBLIC KEY BLOCK----- - * xjMEZKQEMxYJKwYBBAHaRw8BAQdA5oZTq4UPlS0IXn4kEaSqQdAa9+Cq522v - * WYxJQn3vo1/NFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME - * CwkHCAkQJBFPuuhtQo4DFQgKBBYAAgECGQECGwMCHgEWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAAKYYA/jMyDCtJtqu6hj22kq9SW6fuV1FCT2ySJ9vBhumF - * X8wWAP433zVFl4VECOkgGk8qFr8BgkYxaz16GOFAqYbfO6oMBc44BGSkBDMS - * CisGAQQBl1UBBQEBB0AKR+A48zVVYZWQvgu7Opn2IGvzI9jePB/J8pzqRhg2 - * YAMBCAfCeAQYFggAKgUCZKQEMwkQJBFPuuhtQo4CGwwWIQTQ5fbVPB9CWIdf - * XdYkEU+66G1CjgAA0xgBAK4AIahFFnmWR2Mp6A3q021cZXpGklc0Xw1Hfswc - * UYLqAQDfdym4kiUvKO1+REKASt0Gwykndl7hra9txqlUL5DXBQ===Vwgv - * -----END PGP PUBLIC KEY BLOCK-----`; - * - * const publicKey2 = `-----BEGIN PGP PUBLIC KEY BLOCK----- - * xjMEZKQEMxYJKwYBBAHaRw8BAQdAG6h+E+6T/RV2tIHer3FP/jKThAyGcoVx - * FzhnP0hncPzNFEh1bWFuIDxodW1hbkBobXQuYWk+wowEEBYKAD4FAmSkBDME - * CwkHCAkQPIq5xLhlTYkDFQgKBBYAAgECGQECGwMCHgEWIQTcxtMgul/AeUvH - * bio8irnEuGVNiQAA/HsBANpfFkxNYixpsBk8LlaaCaPy5f1/cWNPgODM9uzo - * ciSTAQDtAYynu4dSJO9GbMuDuc0FaUHRWJK3mS6JkvedYL4oBM44BGSkBDMS - * CisGAQQBl1UBBQEBB0DWbEG7DMhkeSc8ZPzrH8XNSCqS3t9y/oQidFR+xN3Z - * bAMBCAfCeAQYFggAKgUCZKQEMwkQPIq5xLhlTYkCGwwWIQTcxtMgul/AeUvH - * bio8irnEuGVNiQAAqt8BAM/4Lw0RVOb0L5Ki9CyxO/6AKvRg4ra3Q3WR+duP - * s/88AQCDErzvn+SOX4s3gvZcM3Vr4wh4Q2syHV8Okgx8STYPDg===DsVk - * -----END PGP PUBLIC KEY BLOCK-----`; - * - * const publicKeys = [publicKey1, publicKey2] - * const result = await EncryptionUtils.encrypt('message', publicKeys); + * const publicKey1 = '-----BEGIN PGP PUBLIC KEY BLOCK-----...'; + * const publicKey2 = '-----BEGIN PGP PUBLIC KEY BLOCK-----...'; + * const publicKeys = [publicKey1, publicKey2]; + * const encryptedMessage = await EncryptionUtils.encrypt('message', publicKeys); + * console.log('Encrypted message:', encryptedMessage); * ``` */ public static async encrypt( @@ -464,25 +340,15 @@ export class EncryptionUtils { /** * Verifies if a message appears to be encrypted with OpenPGP. * - * @param {string} message Message to verify. - * @returns {Promise} `true` if the message appears to be encrypted, `false` if not. - * - * **Code example:** + * @param message - Message to verify. + * @returns `true` if the message appears to be encrypted, `false` if not. * + * @example * ```ts - * const message = `-----BEGIN PGP MESSAGE----- - * - * wV4DqdeRpqH+jaISAQdAsvBFxikvjxRqC7ZlDe98cLd7/aeCEI/AcL8PpVKK - * mC0wKlwxNg/ADi55z9jcYFuMC4kKE+C/teM+JqiI8DO9AwassQUvKFtULnpx - * h2jaOjC/0sAQASjUsIFK8zbuDgk/P8T9Npn6px+GlJPg9K90iwtPWiIp0eyW - * 4zXamJZT51k2DyaUX/Rsc6P4PYhQRKjt0yxtH0jHPmKkLC/9eBeFf4GP0zlZ - * 18xMZ8uCpQCma708Gz0sJYxEz3u/eZdHD7Mc7tWQKyJG8MsTwM1P+fdK1X75 - * L9UryJG2AY+6kKZhG4dqjNxiO4fWluiB2u7iMF+iLEyE3SQCEYorWMC+NDWi - * QIJZ7oQ2w7BaPo1a991gvTOSNm5v2x44KfqPI1uj859BjsQTCA== - * =tsmI - * -----END PGP MESSAGE-----`; + * import { EncryptionUtils } from '@human-protocol/sdk'; * - * const isEncrypted = await EncryptionUtils.isEncrypted(message); + * const message = '-----BEGIN PGP MESSAGE-----...'; + * const isEncrypted = EncryptionUtils.isEncrypted(message); * * if (isEncrypted) { * console.log('The message is encrypted with OpenPGP.'); diff --git a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts index cbbf522dde..9538c9aea0 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts @@ -77,71 +77,52 @@ import { } from './utils'; /** - * ## Introduction - * - * This client enables performing actions on Escrow contracts and obtaining information from both the contracts and subgraph. + * Client to perform actions on Escrow contracts and obtain information from the contracts. * * Internally, the SDK will use one network or another according to the network ID of the `runner`. - * To use this client, it is recommended to initialize it using the static `build` method. - * - * ```ts - * static async build(runner: ContractRunner): Promise; - * ``` + * To use this client, it is recommended to initialize it using the static [`build`](/ts/classes/EscrowClient/#build) method. * * A `Signer` or a `Provider` should be passed depending on the use case of this module: * * - **Signer**: when the user wants to use this model to send transactions calling the contract functions. * - **Provider**: when the user wants to use this model to get information from the contracts or subgraph. * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example + * @example * - * ### Signer + * ###Using Signer * - * **Using private key (backend)** + * ####Using private key (backend) * * ```ts * import { EscrowClient } from '@human-protocol/sdk'; - * import { Wallet, providers } from 'ethers'; + * import { Wallet, JsonRpcProvider } from 'ethers'; * * const rpcUrl = 'YOUR_RPC_URL'; * const privateKey = 'YOUR_PRIVATE_KEY'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); + * const provider = new JsonRpcProvider(rpcUrl); * const signer = new Wallet(privateKey, provider); * const escrowClient = await EscrowClient.build(signer); * ``` * - * **Using Wagmi (frontend)** + * ####Using Wagmi (frontend) * * ```ts - * import { useSigner, useChainId } from 'wagmi'; + * import { useSigner } from 'wagmi'; * import { EscrowClient } from '@human-protocol/sdk'; * * const { data: signer } = useSigner(); * const escrowClient = await EscrowClient.build(signer); * ``` * - * ### Provider + * ###Using Provider * * ```ts * import { EscrowClient } from '@human-protocol/sdk'; - * import { providers } from 'ethers'; + * import { JsonRpcProvider } from 'ethers'; * * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); + * const provider = new JsonRpcProvider(rpcUrl); * const escrowClient = await EscrowClient.build(provider); * ``` */ @@ -151,8 +132,9 @@ export class EscrowClient extends BaseEthersClient { /** * **EscrowClient constructor** * - * @param {ContractRunner} runner The Runner object to interact with the Ethereum network - * @param {NetworkData} networkData The network information required to connect to the Escrow contract + * @param runner - The Runner object to interact with the Ethereum network + * @param networkData - The network information required to connect to the Escrow contract + * @returns An instance of EscrowClient */ constructor(runner: ContractRunner, networkData: NetworkData) { super(runner, networkData); @@ -166,11 +148,10 @@ export class EscrowClient extends BaseEthersClient { /** * Creates an instance of EscrowClient from a Runner. * - * @param {ContractRunner} runner The Runner object to interact with the Ethereum network - * - * @returns {Promise} An instance of EscrowClient - * @throws {ErrorProviderDoesNotExist} Thrown if the provider does not exist for the provided Signer - * @throws {ErrorUnsupportedChainID} Thrown if the network's chainId is not supported + * @param runner - The Runner object to interact with the Ethereum network + * @returns An instance of EscrowClient + * @throws ErrorProviderDoesNotExist If the provider does not exist for the provided Signer + * @throws ErrorUnsupportedChainID If the network's chainId is not supported */ public static async build(runner: ContractRunner): Promise { if (!runner.provider) { @@ -204,28 +185,17 @@ export class EscrowClient extends BaseEthersClient { /** * This function creates an escrow contract that uses the token passed to pay oracle fees and reward workers. + * @remarks Need to have available stake. + * @param tokenAddress - The address of the token to use for escrow funding. + * @param jobRequesterId - Identifier for the job requester. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns Returns the address of the escrow created. + * @throws ErrorInvalidTokenAddress If the token address is invalid + * @throws ErrorLaunchedEventIsNotEmitted If the LaunchedV2 event is not emitted * - * @param {string} tokenAddress - The address of the token to use for escrow funding. - * @param {string} jobRequesterId - Identifier for the job requester. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns {Promise} Returns the address of the escrow created. - * - * - * **Code example** - * - * > Need to have available stake. + * @example * * ```ts - * import { Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * * const tokenAddress = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4'; * const jobRequesterId = "job-requester-id"; * const escrowAddress = await escrowClient.createEscrow(tokenAddress, jobRequesterId); @@ -315,50 +285,45 @@ export class EscrowClient extends BaseEthersClient { /** * Creates, funds, and sets up a new escrow contract in a single transaction. * - * @param {string} tokenAddress - The ERC-20 token address used to fund the escrow. - * @param {bigint} amount - The token amount to fund the escrow with. - * @param {string} jobRequesterId - An off-chain identifier for the job requester. - * @param {IEscrowConfig} escrowConfig - Configuration parameters for escrow setup: - * - `recordingOracle`: Address of the recording oracle. - * - `reputationOracle`: Address of the reputation oracle. - * - `exchangeOracle`: Address of the exchange oracle. - * - `recordingOracleFee`: Fee (in basis points or percentage * 100) for the recording oracle. - * - `reputationOracleFee`: Fee for the reputation oracle. - * - `exchangeOracleFee`: Fee for the exchange oracle. - * - `manifest`: URL to the manifest file. - * - `manifestHash`: Hash of the manifest content. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * - * @returns {Promise} Returns the address of the escrow created. + * @remarks Need to have available stake and approve allowance in the token contract before calling this method. + * @param tokenAddress - The ERC-20 token address used to fund the escrow. + * @param amount - The token amount to fund the escrow with. + * @param jobRequesterId - An off-chain identifier for the job requester. + * @param escrowConfig - Configuration parameters for escrow setup. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns Returns the address of the escrow created. + * @throws ErrorInvalidTokenAddress If the token address is invalid + * @throws ErrorInvalidRecordingOracleAddressProvided If the recording oracle address is invalid + * @throws ErrorInvalidReputationOracleAddressProvided If the reputation oracle address is invalid + * @throws ErrorInvalidExchangeOracleAddressProvided If the exchange oracle address is invalid + * @throws ErrorAmountMustBeGreaterThanZero If any oracle fee is less than or equal to zero + * @throws ErrorTotalFeeMustBeLessThanHundred If the total oracle fees exceed 100 + * @throws ErrorInvalidManifest If the manifest is not a valid URL or JSON string + * @throws ErrorHashIsEmptyString If the manifest hash is empty + * @throws ErrorLaunchedEventIsNotEmitted If the LaunchedV2 event is not emitted * * @example - * import { Wallet, ethers } from 'ethers'; - * import { EscrowClient, IERC20__factory } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * const provider = new ethers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * - * const escrowClient = await EscrowClient.build(signer); + * ```ts + * import { ethers } from 'ethers'; + * import { ERC20__factory } from '@human-protocol/sdk'; * - * const tokenAddress = '0xTokenAddress'; + * const tokenAddress = '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4'; * const amount = ethers.parseUnits('1000', 18); * const jobRequesterId = 'requester-123'; * - * const token = IERC20__factory.connect(tokenAddress, signer); + * const token = ERC20__factory.connect(tokenAddress, signer); * await token.approve(escrowClient.escrowFactoryContract.target, amount); * * const escrowConfig = { - * recordingOracle: '0xRecordingOracle', - * reputationOracle: '0xReputationOracle', - * exchangeOracle: '0xExchangeOracle', + * recordingOracle: '0xRecordingOracleAddress', + * reputationOracle: '0xReputationOracleAddress', + * exchangeOracle: '0xExchangeOracleAddress', * recordingOracleFee: 5n, * reputationOracleFee: 5n, * exchangeOracleFee: 5n, * manifest: 'https://example.com/manifest.json', * manifestHash: 'manifestHash-123', - * } satisfies IEscrowConfig; + * }; * * const escrowAddress = await escrowClient.createFundAndSetupEscrow( * tokenAddress, @@ -366,8 +331,8 @@ export class EscrowClient extends BaseEthersClient { * jobRequesterId, * escrowConfig * ); - * * console.log('Escrow created at:', escrowAddress); + * ``` */ @requiresSigner public async createFundAndSetupEscrow( @@ -431,35 +396,33 @@ export class EscrowClient extends BaseEthersClient { /** * This function sets up the parameters of the escrow. * - * @param {string} escrowAddress Address of the escrow to set up. - * @param {IEscrowConfig} escrowConfig Escrow configuration parameters. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. + * @remarks Only Job Launcher or admin can call it. + * + * @param escrowAddress - Address of the escrow to set up. + * @param escrowConfig - Escrow configuration parameters. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidRecordingOracleAddressProvided If the recording oracle address is invalid + * @throws ErrorInvalidReputationOracleAddressProvided If the reputation oracle address is invalid + * @throws ErrorInvalidExchangeOracleAddressProvided If the exchange oracle address is invalid + * @throws ErrorAmountMustBeGreaterThanZero If any oracle fee is less than or equal to zero + * @throws ErrorTotalFeeMustBeLessThanHundred If the total oracle fees exceed 100 + * @throws ErrorInvalidManifest If the manifest is not a valid URL or JSON string + * @throws ErrorHashIsEmptyString If the manifest hash is empty + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * - * - * **Code example** - * - * > Only Job Launcher or admin can call it. + * @example * * ```ts - * import { Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * * const escrowAddress = '0x62dD51230A30401C455c8398d06F85e4EaB6309f'; * const escrowConfig = { * recordingOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', * reputationOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', * exchangeOracle: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - * recordingOracleFee: BigInt('10'), - * reputationOracleFee: BigInt('10'), - * exchangeOracleFee: BigInt('10'), + * recordingOracleFee: 10n, + * reputationOracleFee: 10n, + * exchangeOracleFee: 10n, * manifest: 'http://localhost/manifest.json', * manifestHash: 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', * }; @@ -519,26 +482,19 @@ export class EscrowClient extends BaseEthersClient { /** * This function adds funds of the chosen token to the escrow. * - * @param {string} escrowAddress Address of the escrow to fund. - * @param {bigint} amount Amount to be added as funds. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** + * @param escrowAddress - Address of the escrow to fund. + * @param amount - Amount to be added as funds. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorAmountMustBeGreaterThanZero If the amount is less than or equal to zero + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); + * import { ethers } from 'ethers'; * - * const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI + * const amount = ethers.parseUnits('5', 'ether'); * await escrowClient.fund('0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); * ``` */ @@ -580,75 +536,74 @@ export class EscrowClient extends BaseEthersClient { } /** - * This function stores the results URL and hash. - * - * @param {string} escrowAddress Address of the escrow. - * @param {string} url Results file URL. - * @param {string} hash Results file hash. - * @param {bigint} fundsToReserve Funds to reserve for payouts - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * + * Stores the result URL and result hash for an escrow. * - * **Code example** + * @remarks Only Recording Oracle or admin can call it. * - * > Only Recording Oracle or admin can call it. + * @param escrowAddress - The escrow address. + * @param url - The URL containing the final results. May be empty only when `fundsToReserve` is `0n`. + * @param hash - The hash of the results payload. + * @param txOptions - Optional transaction overrides. + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the provided escrow address is invalid. + * @throws ErrorInvalidUrl If the URL format is invalid. + * @throws ErrorHashIsEmptyString If the hash is empty and empty values are not allowed. + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow does not exist in the factory. + * @throws ErrorStoreResultsVersion If the contract supports only the deprecated signature. * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * - * await escrowClient.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'http://localhost/results.json', 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079', ethers.parseEther('10')); + * await escrowClient.storeResults( + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * 'https://example.com/results.json', + * '0xHASH123' + * ); * ``` */ - async storeResults( escrowAddress: string, url: string, hash: string, - fundsToReserve: bigint, txOptions?: Overrides ): Promise; /** - * This function stores the results URL and hash. - * - * @param {string} escrowAddress Address of the escrow. - * @param {string} url Results file URL. - * @param {string} hash Results file hash. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. + * Stores the result URL and result hash for an escrow. * + * @remarks Only Recording Oracle or admin can call it. * - * **Code example** + * If `fundsToReserve` is provided, the escrow reserves the specified funds. + * When `fundsToReserve` is `0n`, an empty URL is allowed (for cases where no solutions were provided). * - * > Only Recording Oracle or admin can call it. + * @param escrowAddress - The escrow address. + * @param url - The URL containing the final results. May be empty only when `fundsToReserve` is `0n`. + * @param hash - The hash of the results payload. + * @param fundsToReserve - Optional amount of funds to reserve (when using second overload). + * @param txOptions - Optional transaction overrides. + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the provided escrow address is invalid. + * @throws ErrorInvalidUrl If the URL format is invalid. + * @throws ErrorHashIsEmptyString If the hash is empty and empty values are not allowed. + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow does not exist in the factory. + * @throws ErrorStoreResultsVersion If the contract supports only the deprecated signature. * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; + * import { ethers } from 'ethers'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * - * await escrowClient.storeResults('0x62dD51230A30401C455c8398d06F85e4EaB6309f', 'http://localhost/results.json', 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'); + * await escrowClient.storeResults( + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * 'https://example.com/results.json', + * '0xHASH123', + * ethers.parseEther('5') + * ); * ``` */ async storeResults( escrowAddress: string, url: string, hash: string, + fundsToReserve: bigint, txOptions?: Overrides ): Promise; @@ -715,27 +670,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function sets the status of an escrow to completed. + * @remarks Only Recording Oracle or admin can call it. + * @param escrowAddress - Address of the escrow. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid. + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory. * - * @param {string} escrowAddress Address of the escrow. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * > Only Recording Oracle or admin can call it. - * + * @example * ```ts - * import { Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * * await escrowClient.complete('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); * ``` */ @@ -764,40 +707,48 @@ export class EscrowClient extends BaseEthersClient { /** * This function pays out the amounts specified to the workers and sets the URL of the final results file. + * @remarks Only Reputation Oracle or admin can call it. + * + * @param escrowAddress - Escrow address to payout. + * @param recipients - Array of recipient addresses. + * @param amounts - Array of amounts the recipients will receive. + * @param finalResultsUrl - Final results file URL. + * @param finalResultsHash - Final results file hash. + * @param txId - Transaction ID. + * @param forceComplete - Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorRecipientCannotBeEmptyArray If the recipients array is empty + * @throws ErrorTooManyRecipients If there are too many recipients + * @throws ErrorAmountsCannotBeEmptyArray If the amounts array is empty + * @throws ErrorRecipientAndAmountsMustBeSameLength If recipients and amounts arrays have different lengths + * @throws InvalidEthereumAddressError If any recipient address is invalid + * @throws ErrorInvalidUrl If the final results URL is invalid + * @throws ErrorHashIsEmptyString If the final results hash is empty + * @throws ErrorEscrowDoesNotHaveEnoughBalance If the escrow doesn't have enough balance + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory + * @throws ErrorBulkPayOutVersion If using deprecated signature * - * @param {string} escrowAddress Escrow address to payout. - * @param {string[]} recipients Array of recipient addresses. - * @param {bigint[]} amounts Array of amounts the recipients will receive. - * @param {string} finalResultsUrl Final results file URL. - * @param {string} finalResultsHash Final results file hash. - * @param {number} txId Transaction ID. - * @param {boolean} forceComplete Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * > Only Reputation Oracle or admin can call it. - * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); + * import { ethers } from 'ethers'; * - * const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; - * const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')]; + * const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0x70997970C51812dc3A010C7d01b50e0d17dc79C8']; + * const amounts = [ethers.parseUnits('5', 'ether'), ethers.parseUnits('10', 'ether')]; * const resultsUrl = 'http://localhost/results.json'; * const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'; * const txId = 1; * - * await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId, true); + * await escrowClient.bulkPayOut( + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * recipients, + * amounts, + * resultsUrl, + * resultsHash, + * txId, + * true + * ); * ``` */ async bulkPayOut( @@ -813,41 +764,49 @@ export class EscrowClient extends BaseEthersClient { /** * This function pays out the amounts specified to the workers and sets the URL of the final results file. + * @remarks Only Reputation Oracle or admin can call it. + * @param escrowAddress - Escrow address to payout. + * @param recipients - Array of recipient addresses. + * @param amounts - Array of amounts the recipients will receive. + * @param finalResultsUrl - Final results file URL. + * @param finalResultsHash - Final results file hash. + * @param payoutId - Payout ID. + * @param forceComplete - Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorRecipientCannotBeEmptyArray If the recipients array is empty + * @throws ErrorTooManyRecipients If there are too many recipients + * @throws ErrorAmountsCannotBeEmptyArray If the amounts array is empty + * @throws ErrorRecipientAndAmountsMustBeSameLength If recipients and amounts arrays have different lengths + * @throws InvalidEthereumAddressError If any recipient address is invalid + * @throws ErrorInvalidUrl If the final results URL is invalid + * @throws ErrorHashIsEmptyString If the final results hash is empty + * @throws ErrorEscrowDoesNotHaveEnoughBalance If the escrow doesn't have enough balance + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory + * @throws ErrorBulkPayOutVersion If using deprecated signature * - * @param {string} escrowAddress Escrow address to payout. - * @param {string[]} recipients Array of recipient addresses. - * @param {bigint[]} amounts Array of amounts the recipients will receive. - * @param {string} finalResultsUrl Final results file URL. - * @param {string} finalResultsHash Final results file hash. - * @param {string} payoutId Payout ID. - * @param {boolean} forceComplete Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * > Only Reputation Oracle or admin can call it. + * @example * * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; + * import { ethers } from 'ethers'; * import { v4 as uuidV4 } from 'uuid'; * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * - * const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; - * const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')]; + * const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0x70997970C51812dc3A010C7d01b50e0d17dc79C8']; + * const amounts = [ethers.parseUnits('5', 'ether'), ethers.parseUnits('10', 'ether')]; * const resultsUrl = 'http://localhost/results.json'; * const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'; * const payoutId = uuidV4(); * - * await escrowClient.bulkPayOut('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, payoutId, true); + * await escrowClient.bulkPayOut( + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * recipients, + * amounts, + * resultsUrl, + * resultsHash, + * payoutId, + * true + * ); * ``` */ async bulkPayOut( @@ -925,26 +884,16 @@ export class EscrowClient extends BaseEthersClient { /** * This function cancels the specified escrow and sends the balance to the canceler. + * @remarks Only Job Launcher or admin can call it. + * @param escrowAddress - Address of the escrow to cancel. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * - * @param {string} escrowAddress Address of the escrow to cancel. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * - * - * **Code example** - * - * > Only Job Launcher or admin can call it. + * @example * * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * * await escrowClient.cancel('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); * ``` */ @@ -971,26 +920,16 @@ export class EscrowClient extends BaseEthersClient { /** * This function requests the cancellation of the specified escrow (moves status to ToCancel or finalizes if expired). + * @remarks Only Job Launcher or admin can call it. + * @param escrowAddress - Address of the escrow to request cancellation. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * - * @param {string} escrowAddress Address of the escrow to request cancellation. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * **Code example** - * - * > Only Job Launcher or admin can call it. + * @example * * ```ts - * import { Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * * await escrowClient.requestCancellation('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); * ``` */ @@ -1017,32 +956,25 @@ export class EscrowClient extends BaseEthersClient { /** * This function withdraws additional tokens in the escrow to the canceler. + * @remarks Only Job Launcher or admin can call it. * - * @param {string} escrowAddress Address of the escrow to withdraw. - * @param {string} tokenAddress Address of the token to withdraw. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns {IEscrowWithdraw} Returns the escrow withdrawal data including transaction hash and withdrawal amount. Throws error if any. + * @param escrowAddress - Address of the escrow to withdraw. + * @param tokenAddress - Address of the token to withdraw. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns Returns the escrow withdrawal data including transaction hash and withdrawal amount. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorInvalidTokenAddress If the token address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory + * @throws ErrorTransferEventNotFoundInTransactionLogs If the Transfer event is not found in transaction logs * - * - * **Code example** - * - * > Only Job Launcher or admin can call it. + * @example * * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); - * - * await escrowClient.withdraw( + * const withdrawData = await escrowClient.withdraw( * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', * '0x0376D26246Eb35FF4F9924cF13E6C05fd0bD7Fb4' * ); + * console.log('Withdrawn amount:', withdrawData.withdrawnAmount); * ``` */ @requiresSigner @@ -1108,43 +1040,54 @@ export class EscrowClient extends BaseEthersClient { /** * Creates a prepared transaction for bulk payout without immediately sending it. - * @param {string} escrowAddress Escrow address to payout. - * @param {string[]} recipients Array of recipient addresses. - * @param {bigint[]} amounts Array of amounts the recipients will receive. - * @param {string} finalResultsUrl Final results file URL. - * @param {string} finalResultsHash Final results file hash. - * @param {string} payoutId Payout ID to identify the payout. - * @param {boolean} forceComplete Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns object with raw transaction and signed transaction hash + * @remarks Only Reputation Oracle or admin can call it. + * + * @param escrowAddress - Escrow address to payout. + * @param recipients - Array of recipient addresses. + * @param amounts - Array of amounts the recipients will receive. + * @param finalResultsUrl - Final results file URL. + * @param finalResultsHash - Final results file hash. + * @param payoutId - Payout ID to identify the payout. + * @param forceComplete - Indicates if remaining balance should be transferred to the escrow creator (optional, defaults to false). + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns Returns object with raw transaction and nonce + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorRecipientCannotBeEmptyArray If the recipients array is empty + * @throws ErrorTooManyRecipients If there are too many recipients + * @throws ErrorAmountsCannotBeEmptyArray If the amounts array is empty + * @throws ErrorRecipientAndAmountsMustBeSameLength If recipients and amounts arrays have different lengths + * @throws InvalidEthereumAddressError If any recipient address is invalid + * @throws ErrorInvalidUrl If the final results URL is invalid + * @throws ErrorHashIsEmptyString If the final results hash is empty + * @throws ErrorEscrowDoesNotHaveEnoughBalance If the escrow doesn't have enough balance + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * - * **Code example** - * - * > Only Reputation Oracle or admin can call it. + * @example * * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY' - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const escrowClient = await EscrowClient.build(signer); + * import { ethers } from 'ethers'; + * import { v4 as uuidV4 } from 'uuid'; * - * const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266']; - * const amounts = [ethers.parseUnits(5, 'ether'), ethers.parseUnits(10, 'ether')]; + * const recipients = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0x70997970C51812dc3A010C7d01b50e0d17dc79C8']; + * const amounts = [ethers.parseUnits('5', 'ether'), ethers.parseUnits('10', 'ether')]; * const resultsUrl = 'http://localhost/results.json'; * const resultsHash = 'b5dad76bf6772c0f07fd5e048f6e75a5f86ee079'; - * const payoutId = '372f6916-fe34-4711-b6e3-274f682047de'; + * const payoutId = uuidV4(); * - * const rawTransaction = await escrowClient.createBulkPayoutTransaction('0x62dD51230A30401C455c8398d06F85e4EaB6309f', recipients, amounts, resultsUrl, resultsHash, txId); + * const rawTransaction = await escrowClient.createBulkPayoutTransaction( + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * recipients, + * amounts, + * resultsUrl, + * resultsHash, + * payoutId + * ); * console.log('Raw transaction:', rawTransaction); * * const signedTransaction = await signer.signTransaction(rawTransaction); * console.log('Tx hash:', ethers.keccak256(signedTransaction)); - * (await signer.sendTransaction(rawTransaction)).wait(); + * await signer.sendTransaction(rawTransaction); + * ``` */ @requiresSigner async createBulkPayoutTransaction( @@ -1275,21 +1218,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the balance for a specified escrow address. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Balance of the escrow in the token used to fund it. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Balance of the escrow in the token used to fund it. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const balance = await escrowClient.getBalance('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Balance:', balance); * ``` */ async getBalance(escrowAddress: string): Promise { @@ -1319,21 +1256,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the reserved funds for a specified escrow address. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Reserved funds of the escrow in the token used to fund it. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Reserved funds of the escrow in the token used to fund it. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const reservedFunds = await escrowClient.getReservedFunds('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Reserved funds:', reservedFunds); * ``` */ async getReservedFunds(escrowAddress: string): Promise { @@ -1356,21 +1287,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the manifest file hash. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Hash of the manifest file content. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Hash of the manifest file content. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const manifestHash = await escrowClient.getManifestHash('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Manifest hash:', manifestHash); * ``` */ async getManifestHash(escrowAddress: string): Promise { @@ -1394,21 +1319,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the manifest. Could be a URL or a JSON string. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Url of the manifest. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Manifest URL or JSON string. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const manifest = await escrowClient.getManifest('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Manifest:', manifest); * ``` */ async getManifest(escrowAddress: string): Promise { @@ -1432,21 +1351,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the results file URL. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Results file url. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Results file URL. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const resultsUrl = await escrowClient.getResultsUrl('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Results URL:', resultsUrl); * ``` */ async getResultsUrl(escrowAddress: string): Promise { @@ -1470,21 +1383,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the intermediate results file URL. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Url of the file that store results from Recording Oracle. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns URL of the file that stores results from Recording Oracle. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const intermediateResultsUrl = await escrowClient.getIntermediateResultsUrl('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Intermediate results URL:', intermediateResultsUrl); * ``` */ async getIntermediateResultsUrl(escrowAddress: string): Promise { @@ -1508,21 +1415,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the intermediate results hash. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Hash of the intermediate results file content. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Hash of the intermediate results file content. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const intermediateResultsHash = await escrowClient.getIntermediateResultsHash('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Intermediate results hash:', intermediateResultsHash); * ``` */ async getIntermediateResultsHash(escrowAddress: string): Promise { @@ -1546,21 +1447,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the token address used for funding the escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Address of the token used to fund the escrow. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Address of the token used to fund the escrow. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const tokenAddress = await escrowClient.getTokenAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Token address:', tokenAddress); * ``` */ async getTokenAddress(escrowAddress: string): Promise { @@ -1584,21 +1479,17 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the current status of the escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Current status of the escrow. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Current status of the escrow. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); + * import { EscrowStatus } from '@human-protocol/sdk'; * * const status = await escrowClient.getStatus('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Status:', EscrowStatus[status]); * ``` */ async getStatus(escrowAddress: string): Promise { @@ -1622,21 +1513,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the recording oracle address for a given escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Address of the Recording Oracle. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Address of the Recording Oracle. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const oracleAddress = await escrowClient.getRecordingOracleAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Recording Oracle address:', oracleAddress); * ``` */ async getRecordingOracleAddress(escrowAddress: string): Promise { @@ -1660,21 +1545,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the job launcher address for a given escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Address of the Job Launcher. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Address of the Job Launcher. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const jobLauncherAddress = await escrowClient.getJobLauncherAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Job Launcher address:', jobLauncherAddress); * ``` */ async getJobLauncherAddress(escrowAddress: string): Promise { @@ -1698,21 +1577,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the reputation oracle address for a given escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Address of the Reputation Oracle. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Address of the Reputation Oracle. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const oracleAddress = await escrowClient.getReputationOracleAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Reputation Oracle address:', oracleAddress); * ``` */ async getReputationOracleAddress(escrowAddress: string): Promise { @@ -1736,21 +1609,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the exchange oracle address for a given escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Address of the Exchange Oracle. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Address of the Exchange Oracle. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const oracleAddress = await escrowClient.getExchangeOracleAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Exchange Oracle address:', oracleAddress); * ``` */ async getExchangeOracleAddress(escrowAddress: string): Promise { @@ -1774,21 +1641,15 @@ export class EscrowClient extends BaseEthersClient { /** * This function returns the escrow factory address for a given escrow. * - * @param {string} escrowAddress Address of the escrow. - * @returns {Promise} Address of the escrow factory. - * - * **Code example** + * @param escrowAddress - Address of the escrow. + * @returns Address of the escrow factory. + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory * + * @example * ```ts - * import { providers } from 'ethers'; - * import { EscrowClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const escrowClient = await EscrowClient.build(provider); - * * const factoryAddress = await escrowClient.getFactoryAddress('0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * console.log('Factory address:', factoryAddress); * ``` */ async getFactoryAddress(escrowAddress: string): Promise { @@ -1810,138 +1671,40 @@ export class EscrowClient extends BaseEthersClient { } } /** - * ## Introduction - * - * Utility class for escrow-related operations. - * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example - * - * ### Signer - * - * **Using private key(backend)** + * Utility helpers for escrow-related queries. * + * @example * ```ts * import { ChainId, EscrowUtils } from '@human-protocol/sdk'; * - * const escrowAddresses = new EscrowUtils.getEscrows({ + * const escrows = await EscrowUtils.getEscrows({ * chainId: ChainId.POLYGON_AMOY * }); + * console.log('Escrows:', escrows); * ``` */ export class EscrowUtils { /** * This function returns an array of escrows based on the specified filter parameters. * + * @param filter - Filter parameters. + * @param options - Optional configuration for subgraph requests. + * @returns List of escrows that match the filter. + * @throws ErrorInvalidAddress If any filter address is invalid + * @throws ErrorUnsupportedChainID If the chain ID is not supported * - * **Input parameters** - * - * ```ts - * interface IEscrowsFilter { - * chainId: ChainId; - * launcher?: string; - * reputationOracle?: string; - * recordingOracle?: string; - * exchangeOracle?: string; - * jobRequesterId?: string; - * status?: EscrowStatus; - * from?: Date; - * to?: Date; - * first?: number; - * skip?: number; - * orderDirection?: OrderDirection; - * } - * ``` - * - * ```ts - * enum ChainId { - * ALL = -1, - * MAINNET = 1, - * SEPOLIA = 11155111, - * BSC_MAINNET = 56, - * BSC_TESTNET = 97, - * POLYGON = 137, - * POLYGON_AMOY=80002, - * LOCALHOST = 1338, - * } - * ``` - * - * ```ts - * enum OrderDirection { - * ASC = 'asc', - * DESC = 'desc', - * } - * ``` - * - * ```ts - * enum EscrowStatus { - * Launched, - * Pending, - * Partial, - * Paid, - * Complete, - * Cancelled, - * } - * ``` - * - * ```ts - * interface IEscrow { - * id: string; - * address: string; - * amountPaid: bigint; - * balance: bigint; - * count: bigint; - * factoryAddress: string; - * finalResultsUrl: string | null; - * finalResultsHash: string | null; - * intermediateResultsUrl: string | null; - * intermediateResultsHash: string | null; - * launcher: string; - * jobRequesterId: string | null; - * manifestHash: string | null; - * manifest: string | null; - * recordingOracle: string | null; - * reputationOracle: string | null; - * exchangeOracle: string | null; - * recordingOracleFee: number | null; - * reputationOracleFee: number | null; - * exchangeOracleFee: number | null; - * status: string; - * token: string; - * totalFundedAmount: bigint; - * createdAt: number; - * chainId: number; - * }; - * ``` - * - * - * @param {IEscrowsFilter} filter Filter parameters. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {IEscrow[]} List of escrows that match the filter. - * - * **Code example** - * + * @example * ```ts - * import { ChainId, EscrowUtils, EscrowStatus } from '@human-protocol/sdk'; + * import { ChainId, EscrowStatus } from '@human-protocol/sdk'; * - * const filters: IEscrowsFilter = { + * const filters = { * status: EscrowStatus.Pending, * from: new Date(2023, 4, 8), * to: new Date(2023, 5, 8), * chainId: ChainId.POLYGON_AMOY * }; * const escrows = await EscrowUtils.getEscrows(filters); + * console.log('Found escrows:', escrows.length); * ``` */ public static async getEscrows( @@ -2006,63 +1769,24 @@ export class EscrowUtils { * * > This uses Subgraph * - * **Input parameters** - * - * ```ts - * enum ChainId { - * ALL = -1, - * MAINNET = 1, - * SEPOLIA = 11155111, - * BSC_MAINNET = 56, - * BSC_TESTNET = 97, - * POLYGON = 137, - * POLYGON_AMOY = 80002, - * LOCALHOST = 1338, - * } - * ``` - * - * ```ts - * interface IEscrow { - * id: string; - * address: string; - * amountPaid: bigint; - * balance: bigint; - * count: bigint; - * factoryAddress: string; - * finalResultsUrl: string | null; - * finalResultsHash: string | null; - * intermediateResultsUrl: string | null; - * intermediateResultsHash: string | null; - * launcher: string; - * jobRequesterId: string | null; - * manifestHash: string | null; - * manifest: string | null; - * recordingOracle: string | null; - * reputationOracle: string | null; - * exchangeOracle: string | null; - * recordingOracleFee: number | null; - * reputationOracleFee: number | null; - * exchangeOracleFee: number | null; - * status: string; - * token: string; - * totalFundedAmount: bigint; - * createdAt: number; - * chainId: number; - * }; - * ``` - * - * - * @param {ChainId} chainId Network in which the escrow has been deployed - * @param {string} escrowAddress Address of the escrow - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} - Escrow data or null if not found. - * - * **Code example** + * @param chainId - Network in which the escrow has been deployed + * @param escrowAddress - Address of the escrow + * @param options - Optional configuration for subgraph requests. + * @returns Escrow data or null if not found. + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorInvalidAddress If the escrow address is invalid * + * @example * ```ts - * import { ChainId, EscrowUtils } from '@human-protocol/sdk'; + * import { ChainId } from '@human-protocol/sdk'; * - * const escrow = new EscrowUtils.getEscrow(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890"); + * const escrow = await EscrowUtils.getEscrow( + * ChainId.POLYGON_AMOY, + * "0x1234567890123456789012345678901234567890" + * ); + * if (escrow) { + * console.log('Escrow status:', escrow.status); + * } * ``` */ public static async getEscrow( @@ -2096,56 +1820,25 @@ export class EscrowUtils { * * > This uses Subgraph * - * **Input parameters** - * - * ```ts - * enum ChainId { - * ALL = -1, - * MAINNET = 1, - * SEPOLIA = 11155111, - * BSC_MAINNET = 56, - * BSC_TESTNET = 97, - * POLYGON = 137, - * POLYGON_AMOY = 80002, - * LOCALHOST = 1338, - * } - * ``` - * - * ```ts - * enum OrderDirection { - * ASC = 'asc', - * DESC = 'desc', - * } - * ``` + * @param filter - Filter parameters. + * @param options - Optional configuration for subgraph requests. + * @returns Array of status events with their corresponding statuses. + * @throws ErrorInvalidAddress If the launcher address is invalid + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts - * type Status = { - * escrowAddress: string; - * timestamp: string; - * status: string; - * }; - * ``` - * - * @param {IStatusEventFilter} filter Filter parameters. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} - Array of status events with their corresponding statuses. + * import { ChainId, EscrowStatus } from '@human-protocol/sdk'; * - * **Code example** - * - * ```ts - * import { ChainId, EscrowUtils, EscrowStatus } from '@human-protocol/sdk'; - * - * (async () => { - * const fromDate = new Date('2023-01-01'); - * const toDate = new Date('2023-12-31'); - * const statusEvents = await EscrowUtils.getStatusEvents({ - * chainId: ChainId.POLYGON, - * statuses: [EscrowStatus.Pending, EscrowStatus.Complete], - * from: fromDate, - * to: toDate - * }); - * console.log(statusEvents); - * })(); + * const fromDate = new Date('2023-01-01'); + * const toDate = new Date('2023-12-31'); + * const statusEvents = await EscrowUtils.getStatusEvents({ + * chainId: ChainId.POLYGON, + * statuses: [EscrowStatus.Pending, EscrowStatus.Complete], + * from: fromDate, + * to: toDate + * }); + * console.log('Status events:', statusEvents.length); * ``` */ public static async getStatusEvents( @@ -2218,17 +1911,15 @@ export class EscrowUtils { * * > This uses Subgraph * - * **Input parameters** - * Fetch payouts from the subgraph. - * - * @param {IPayoutFilter} filter Filter parameters. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} List of payouts matching the filters. - * - * **Code example** + * @param filter - Filter parameters. + * @param options - Optional configuration for subgraph requests. + * @returns List of payouts matching the filters. + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorInvalidAddress If any filter address is invalid * + * @example * ```ts - * import { ChainId, EscrowUtils } from '@human-protocol/sdk'; + * import { ChainId } from '@human-protocol/sdk'; * * const payouts = await EscrowUtils.getPayouts({ * chainId: ChainId.POLYGON, @@ -2237,7 +1928,7 @@ export class EscrowUtils { * from: new Date('2023-01-01'), * to: new Date('2023-12-31') * }); - * console.log(payouts); + * console.log('Payouts:', payouts.length); * ``` */ public static async getPayouts( @@ -2292,48 +1983,22 @@ export class EscrowUtils { * * > This uses Subgraph * - * **Input parameters** - * - * ```ts - * enum ChainId { - * ALL = -1, - * MAINNET = 1, - * SEPOLIA = 11155111, - * BSC_MAINNET = 56, - * BSC_TESTNET = 97, - * POLYGON = 137, - * POLYGON_AMOY = 80002, - * LOCALHOST = 1338, - * } - * ``` - * - * ```ts - * interface ICancellationRefund { - * id: string; - * escrowAddress: string; - * receiver: string; - * amount: bigint; - * block: number; - * timestamp: number; - * txHash: string; - * }; - * ``` - * - * - * @param {Object} filter Filter parameters. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} List of cancellation refunds matching the filters. - * - * **Code example** + * @param filter - Filter parameters. + * @param options - Optional configuration for subgraph requests. + * @returns List of cancellation refunds matching the filters. + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorInvalidAddress If the receiver address is invalid * + * @example * ```ts - * import { ChainId, EscrowUtils } from '@human-protocol/sdk'; + * import { ChainId } from '@human-protocol/sdk'; * * const cancellationRefunds = await EscrowUtils.getCancellationRefunds({ * chainId: ChainId.POLYGON_AMOY, * escrowAddress: '0x1234567890123456789012345678901234567890', * }); - * console.log(cancellationRefunds); + * console.log('Cancellation refunds:', cancellationRefunds.length); * ``` */ public static async getCancellationRefunds( @@ -2391,45 +2056,25 @@ export class EscrowUtils { * * > This uses Subgraph * - * **Input parameters** - * - * ```ts - * enum ChainId { - * ALL = -1, - * MAINNET = 1, - * SEPOLIA = 11155111, - * BSC_MAINNET = 56, - * BSC_TESTNET = 97, - * POLYGON = 137, - * POLYGON_AMOY = 80002, - * LOCALHOST = 1338, - * } - * ``` + * @param chainId - Network in which the escrow has been deployed + * @param escrowAddress - Address of the escrow + * @param options - Optional configuration for subgraph requests. + * @returns Cancellation refund data or null if not found. + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid * + * @example * ```ts - * interface ICancellationRefund { - * id: string; - * escrowAddress: string; - * receiver: string; - * amount: bigint; - * block: number; - * timestamp: number; - * txHash: string; - * }; - * ``` - * - * - * @param {ChainId} chainId Network in which the escrow has been deployed - * @param {string} escrowAddress Address of the escrow - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Cancellation refund data + * import { ChainId } from '@human-protocol/sdk'; * - * **Code example** * - * ```ts - * import { ChainId, EscrowUtils } from '@human-protocol/sdk'; - * - * const cancellationRefund = await EscrowUtils.getCancellationRefund(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890"); + * const cancellationRefund = await EscrowUtils.getCancellationRefund( + * ChainId.POLYGON_AMOY, + * "0x1234567890123456789012345678901234567890" + * ); + * if (cancellationRefund) { + * console.log('Refund amount:', cancellationRefund.amount); + * } * ``` */ public static async getCancellationRefund( diff --git a/packages/sdk/typescript/human-protocol-sdk/src/index.ts b/packages/sdk/typescript/human-protocol-sdk/src/index.ts index 15a363bae2..0e07f51949 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/index.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/index.ts @@ -1,8 +1,8 @@ import { StakingClient, StakingUtils } from './staking'; import { KVStoreClient, KVStoreUtils } from './kvstore'; import { EscrowClient, EscrowUtils } from './escrow'; -import { StatisticsClient } from './statistics'; -import { Encryption, EncryptionUtils } from './encryption'; +import { StatisticsUtils } from './statistics'; +import { Encryption, EncryptionUtils, MessageDataType } from './encryption'; import { OperatorUtils } from './operator'; import { TransactionUtils } from './transaction'; import { WorkerUtils } from './worker'; @@ -30,11 +30,12 @@ export { KVStoreUtils, EscrowClient, EscrowUtils, - StatisticsClient, + StatisticsUtils, Encryption, EncryptionUtils, OperatorUtils, TransactionUtils, WorkerUtils, StakingUtils, + MessageDataType, }; diff --git a/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts b/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts index c30ca0f9d4..96ec49bf29 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/kvstore.ts @@ -26,12 +26,10 @@ import { import { KVStoreData } from './graphql'; import { IKVStore, SubgraphOptions } from './interfaces'; /** - * ## Introduction - * - * This client enables performing actions on KVStore contract and obtaining information from both the contracts and subgraph. + * Client for interacting with the KVStore contract. * * Internally, the SDK will use one network or another according to the network ID of the `runner`. - * To use this client, it is recommended to initialize it using the static `build` method. + * To use this client, it is recommended to initialize it using the static [`build`](/ts/classes/KVStoreClient/#build) method. * * ```ts * static async build(runner: ContractRunner): Promise; @@ -42,37 +40,25 @@ import { IKVStore, SubgraphOptions } from './interfaces'; * - **Signer**: when the user wants to use this model to send transactions calling the contract functions. * - **Provider**: when the user wants to use this model to get information from the contracts or subgraph. * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example + * @example * - * ### Signer + * ###Using Signer * - * **Using private key (backend)** + * ####Using private key (backend) * * ```ts * import { KVStoreClient } from '@human-protocol/sdk'; - * import { Wallet, providers } from 'ethers'; + * import { Wallet, JsonRpcProvider } from 'ethers'; * * const rpcUrl = 'YOUR_RPC_URL'; * const privateKey = 'YOUR_PRIVATE_KEY'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); + * const provider = new JsonRpcProvider(rpcUrl); * const signer = new Wallet(privateKey, provider); * const kvstoreClient = await KVStoreClient.build(signer); * ``` * - * **Using Wagmi (frontend)** + * ####Using Wagmi (frontend) * * ```ts * import { useSigner, useChainId } from 'wagmi'; @@ -82,15 +68,15 @@ import { IKVStore, SubgraphOptions } from './interfaces'; * const kvstoreClient = await KVStoreClient.build(signer); * ``` * - * ### Provider + * ###Using Provider * * ```ts * import { KVStoreClient } from '@human-protocol/sdk'; - * import { providers } from 'ethers'; + * import { JsonRpcProvider } from 'ethers'; * * const rpcUrl = 'YOUR_RPC_URL'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); + * const provider = new JsonRpcProvider(rpcUrl); * const kvstoreClient = await KVStoreClient.build(provider); * ``` */ @@ -101,8 +87,8 @@ export class KVStoreClient extends BaseEthersClient { /** * **KVStoreClient constructor** * - * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network - * @param {NetworkData} networkData - The network information required to connect to the KVStore contract + * @param runner - The Runner object to interact with the Ethereum network + * @param networkData - The network information required to connect to the KVStore contract */ constructor(runner: ContractRunner, networkData: NetworkData) { super(runner, networkData); @@ -116,11 +102,23 @@ export class KVStoreClient extends BaseEthersClient { /** * Creates an instance of KVStoreClient from a runner. * - * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network + * @param runner - The Runner object to interact with the Ethereum network + * @returns An instance of KVStoreClient + * @throws ErrorProviderDoesNotExist If the provider does not exist for the provided Signer + * @throws ErrorUnsupportedChainID If the network's chainId is not supported * - * @returns {Promise} - An instance of KVStoreClient - * @throws {ErrorProviderDoesNotExist} - Thrown if the provider does not exist for the provided Signer - * @throws {ErrorUnsupportedChainID} - Thrown if the network's chainId is not supported + * @example + * ```ts + * import { KVStoreClient } from '@human-protocol/sdk'; + * import { Wallet, JsonRpcProvider } from 'ethers'; + * + * const rpcUrl = 'YOUR_RPC_URL'; + * const privateKey = 'YOUR_PRIVATE_KEY'; + * + * const provider = new JsonRpcProvider(rpcUrl); + * const signer = new Wallet(privateKey, provider); + * const kvstoreClient = await KVStoreClient.build(signer); + * ``` */ public static async build(runner: ContractRunner): Promise { if (!runner.provider) { @@ -142,27 +140,15 @@ export class KVStoreClient extends BaseEthersClient { /** * This function sets a key-value pair associated with the address that submits the transaction. * - * @param {string} key Key of the key-value pair - * @param {string} value Value of the key-value pair - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * > Need to have available stake. + * @param key - Key of the key-value pair + * @param value - Value of the key-value pair + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorKVStoreEmptyKey If the key is empty + * @throws Error If the transaction fails * + * @example * ```ts - * import { Wallet, providers } from 'ethers'; - * import { KVStoreClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const kvstoreClient = await KVStoreClient.build(signer); - * * await kvstoreClient.set('Role', 'RecordingOracle'); * ``` */ @@ -183,27 +169,16 @@ export class KVStoreClient extends BaseEthersClient { /** * This function sets key-value pairs in bulk associated with the address that submits the transaction. * - * @param {string[]} keys Array of keys (keys and value must have the same order) - * @param {string[]} values Array of values - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** - * - * > Need to have available stake. + * @param keys - Array of keys (keys and value must have the same order) + * @param values - Array of values + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorKVStoreArrayLength If keys and values arrays have different lengths + * @throws ErrorKVStoreEmptyKey If any key is empty + * @throws Error If the transaction fails * + * @example * ```ts - * import { Wallet, providers } from 'ethers'; - * import { KVStoreClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const kvstoreClient = await KVStoreClient.build(signer); - * * const keys = ['role', 'webhook_url']; * const values = ['RecordingOracle', 'http://localhost']; * await kvstoreClient.setBulk(keys, values); @@ -229,25 +204,15 @@ export class KVStoreClient extends BaseEthersClient { /** * Sets a URL value for the address that submits the transaction, and its hash. * - * @param {string} url URL to set - * @param {string | undefined} urlKey Configurable URL key. `url` by default. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * - * **Code example** + * @param url - URL to set + * @param urlKey - Configurable URL key. `url` by default. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidUrl If the URL is invalid + * @throws Error If the transaction fails * + * @example * ```ts - * import { Wallet, providers } from 'ethers'; - * import { KVStoreClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const kvstoreClient = await KVStoreClient.build(signer); - * * await kvstoreClient.setFileUrlAndHash('example.com'); * await kvstoreClient.setFileUrlAndHash('linkedin.com/example', 'linkedin_url'); * ``` @@ -283,26 +248,17 @@ export class KVStoreClient extends BaseEthersClient { /** * Gets the value of a key-value pair in the contract. * - * @param {string} address Address from which to get the key value. - * @param {string} key Key to obtain the value. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {string} Value of the key. - * - * - * **Code example** - * - * > Need to have available stake. + * @param address - Address from which to get the key value. + * @param key - Key to obtain the value. + * @returns Value of the key. + * @throws ErrorKVStoreEmptyKey If the key is empty + * @throws ErrorInvalidAddress If the address is invalid + * @throws Error If the contract call fails * + * @example * ```ts - * import { providers } from 'ethers'; - * import { KVStoreClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const kvstoreClient = await KVStoreClient.build(provider); - * * const value = await kvstoreClient.get('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', 'Role'); + * console.log('Value:', value); * ``` */ public async get(address: string, key: string): Promise { @@ -320,55 +276,37 @@ export class KVStoreClient extends BaseEthersClient { } /** - * ## Introduction - * - * Utility class for KVStore-related operations. - * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example - * - * ### Signer - * - * **Using private key (backend)** + * Utility helpers for KVStore-related queries. * + * @example * ```ts * import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; * - * const KVStoreAddresses = await KVStoreUtils.getKVStoreData( + * const kvStoreData = await KVStoreUtils.getKVStoreData( * ChainId.POLYGON_AMOY, * "0x1234567890123456789012345678901234567890" * ); + * console.log('KVStore data:', kvStoreData); * ``` */ export class KVStoreUtils { /** * This function returns the KVStore data for a given address. * - * @param {ChainId} chainId Network in which the KVStore is deployed - * @param {string} address Address of the KVStore - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} KVStore data - * @throws {ErrorUnsupportedChainID} - Thrown if the network's chainId is not supported - * @throws {ErrorInvalidAddress} - Thrown if the Address sent is invalid - * - * **Code example** + * @param chainId - Network in which the KVStore is deployed + * @param address - Address of the KVStore + * @param options - Optional configuration for subgraph requests. + * @returns KVStore data + * @throws ErrorUnsupportedChainID If the network's chainId is not supported + * @throws ErrorInvalidAddress If the address is invalid * + * @example * ```ts - * import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - * - * const kvStoreData = await KVStoreUtils.getKVStoreData(ChainId.POLYGON_AMOY, "0x1234567890123456789012345678901234567890"); - * console.log(kvStoreData); + * const kvStoreData = await KVStoreUtils.getKVStoreData( + * ChainId.POLYGON_AMOY, + * "0x1234567890123456789012345678901234567890" + * ); + * console.log('KVStore data:', kvStoreData); * ``` */ public static async getKVStoreData( @@ -404,26 +342,24 @@ export class KVStoreUtils { /** * Gets the value of a key-value pair in the KVStore using the subgraph. * - * @param {ChainId} chainId Network in which the KVStore is deployed - * @param {string} address Address from which to get the key value. - * @param {string} key Key to obtain the value. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Value of the key. - * @throws {ErrorUnsupportedChainID} - Thrown if the network's chainId is not supported - * @throws {ErrorInvalidAddress} - Thrown if the Address sent is invalid - * @throws {ErrorKVStoreEmptyKey} - Thrown if the key is empty - * - * **Code example** - * + * @param chainId - Network in which the KVStore is deployed + * @param address - Address from which to get the key value. + * @param key - Key to obtain the value. + * @param options - Optional configuration for subgraph requests. + * @returns Value of the key. + * @throws ErrorUnsupportedChainID If the network's chainId is not supported + * @throws ErrorInvalidAddress If the address is invalid + * @throws ErrorKVStoreEmptyKey If the key is empty + * @throws InvalidKeyError If the key is not found + * + * @example * ```ts - * import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - * - * const chainId = ChainId.POLYGON_AMOY; - * const address = '0x1234567890123456789012345678901234567890'; - * const key = 'role'; - * - * const value = await KVStoreUtils.get(chainId, address, key); - * console.log(value); + * const value = await KVStoreUtils.get( + * ChainId.POLYGON_AMOY, + * '0x1234567890123456789012345678901234567890', + * 'role' + * ); + * console.log('Value:', value); * ``` */ public static async get( @@ -458,22 +394,22 @@ export class KVStoreUtils { /** * Gets the URL value of the given entity, and verifies its hash. * - * @param {ChainId} chainId Network in which the KVStore is deployed - * @param {string} address Address from which to get the URL value. - * @param {string} urlKey Configurable URL key. `url` by default. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} URL value for the given address if it exists, and the content is valid - * - * **Code example** + * @param chainId - Network in which the KVStore is deployed + * @param address - Address from which to get the URL value. + * @param urlKey - Configurable URL key. `url` by default. + * @param options - Optional configuration for subgraph requests. + * @returns URL value for the given address if it exists, and the content is valid + * @throws ErrorInvalidAddress If the address is invalid + * @throws ErrorInvalidHash If the hash verification fails + * @throws Error If fetching URL or hash fails * + * @example * ```ts - * import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - * - * const chainId = ChainId.POLYGON_AMOY; - * const address = '0x1234567890123456789012345678901234567890'; - * - * const url = await KVStoreUtils.getFileUrlAndVerifyHash(chainId, address); - * console.log(url); + * const url = await KVStoreUtils.getFileUrlAndVerifyHash( + * ChainId.POLYGON_AMOY, + * '0x1234567890123456789012345678901234567890' + * ); + * console.log('Verified URL:', url); * ``` */ public static async getFileUrlAndVerifyHash( @@ -521,20 +457,21 @@ export class KVStoreUtils { /** * Gets the public key of the given entity, and verifies its hash. * - * @param {ChainId} chainId Network in which the KVStore is deployed - * @param {string} address Address from which to get the public key. - * @returns {Promise} Public key for the given address if it exists, and the content is valid - * - * **Code example** + * @param chainId - Network in which the KVStore is deployed + * @param address - Address from which to get the public key. + * @param options - Optional configuration for subgraph requests. + * @returns Public key for the given address if it exists, and the content is valid + * @throws ErrorInvalidAddress If the address is invalid + * @throws ErrorInvalidHash If the hash verification fails + * @throws Error If fetching the public key fails * + * @example * ```ts - * import { ChainId, KVStoreUtils } from '@human-protocol/sdk'; - * - * const chainId = ChainId.POLYGON_AMOY; - * const address = '0x1234567890123456789012345678901234567890'; - * - * const publicKey = await KVStoreUtils.getPublicKey(chainId, address); - * console.log(publicKey); + * const publicKey = await KVStoreUtils.getPublicKey( + * ChainId.POLYGON_AMOY, + * '0x1234567890123456789012345678901234567890' + * ); + * console.log('Public key:', publicKey); * ``` */ public static async getPublicKey( diff --git a/packages/sdk/typescript/human-protocol-sdk/src/operator.ts b/packages/sdk/typescript/human-protocol-sdk/src/operator.ts index 2428c9d24e..ad0dd150d7 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/operator.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/operator.ts @@ -26,21 +26,40 @@ import { getSubgraphUrl, customGqlFetch } from './utils'; import { ChainId, OrderDirection } from './enums'; import { NETWORKS } from './constants'; +/** + * Utility helpers for operator-related queries. + * + * @example + * ```ts + * import { OperatorUtils, ChainId } from '@human-protocol/sdk'; + * + * const operator = await OperatorUtils.getOperator( + * ChainId.POLYGON_AMOY, + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + * ); + * console.log('Operator:', operator); + * ``` + */ export class OperatorUtils { /** * This function returns the operator data for the given address. * - * @param {ChainId} chainId Network in which the operator is deployed - * @param {string} address Operator address. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} - Returns the operator details or null if not found. - * - * **Code example** + * @param chainId - Network in which the operator is deployed + * @param address - Operator address. + * @param options - Optional configuration for subgraph requests. + * @returns Returns the operator details or null if not found. + * @throws ErrorInvalidStakerAddressProvided If the address is invalid + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts * import { OperatorUtils, ChainId } from '@human-protocol/sdk'; * - * const operator = await OperatorUtils.getOperator(ChainId.POLYGON_AMOY, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * const operator = await OperatorUtils.getOperator( + * ChainId.POLYGON_AMOY, + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + * ); + * console.log('Operator:', operator); * ``` */ public static async getOperator( @@ -74,19 +93,20 @@ export class OperatorUtils { /** * This function returns all the operator details of the protocol. * - * @param {IOperatorsFilter} filter Filter for the operators. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Returns an array with all the operator details. - * - * **Code example** + * @param filter - Filter for the operators. + * @param options - Optional configuration for subgraph requests. + * @returns Returns an array with all the operator details. + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts - * import { OperatorUtils, ChainId } from '@human-protocol/sdk'; + * import { ChainId } from '@human-protocol/sdk'; * - * const filter: IOperatorsFilter = { - * chainId: ChainId.POLYGON + * const filter = { + * chainId: ChainId.POLYGON_AMOY * }; * const operators = await OperatorUtils.getOperators(filter); + * console.log('Operators:', operators.length); * ``` */ public static async getOperators( @@ -142,18 +162,22 @@ export class OperatorUtils { /** * Retrieves the reputation network operators of the specified address. * - * @param {ChainId} chainId Network in which the reputation network is deployed - * @param {string} address Address of the reputation oracle. - * @param {string} [role] - (Optional) Role of the operator. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} - Returns an array of operator details. - * - * **Code example** + * @param chainId - Network in which the reputation network is deployed + * @param address - Address of the reputation oracle. + * @param role - Role of the operator (optional). + * @param options - Optional configuration for subgraph requests. + * @returns Returns an array of operator details. + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts * import { OperatorUtils, ChainId } from '@human-protocol/sdk'; * - * const operators = await OperatorUtils.getReputationNetworkOperators(ChainId.POLYGON_AMOY, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * const operators = await OperatorUtils.getReputationNetworkOperators( + * ChainId.POLYGON_AMOY, + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + * ); + * console.log('Operators:', operators.length); * ``` */ public static async getReputationNetworkOperators( @@ -189,17 +213,22 @@ export class OperatorUtils { /** * This function returns information about the rewards for a given slasher address. * - * @param {ChainId} chainId Network in which the rewards are deployed - * @param {string} slasherAddress Slasher address. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Returns an array of Reward objects that contain the rewards earned by the user through slashing other users. - * - * **Code example** + * @param chainId - Network in which the rewards are deployed + * @param slasherAddress - Slasher address. + * @param options - Optional configuration for subgraph requests. + * @returns Returns an array of Reward objects that contain the rewards earned by the user through slashing other users. + * @throws ErrorInvalidSlasherAddressProvided If the slasher address is invalid + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts * import { OperatorUtils, ChainId } from '@human-protocol/sdk'; * - * const rewards = await OperatorUtils.getRewards(ChainId.POLYGON_AMOY, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * const rewards = await OperatorUtils.getRewards( + * ChainId.POLYGON_AMOY, + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + * ); + * console.log('Rewards:', rewards.length); * ``` */ public static async getRewards( diff --git a/packages/sdk/typescript/human-protocol-sdk/src/staking.ts b/packages/sdk/typescript/human-protocol-sdk/src/staking.ts index eac6ffb8d3..c39669db25 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/staking.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/staking.ts @@ -37,9 +37,7 @@ import { } from './graphql/queries/staking'; /** - * ## Introduction - * - * This client enables performing actions on staking contracts and obtaining staking information from both the contracts and subgraph. + * Client for staking actions on HUMAN Protocol. * * Internally, the SDK will use one network or another according to the network ID of the `runner`. * To use this client, it is recommended to initialize it using the static `build` method. @@ -53,37 +51,25 @@ import { * - **Signer**: when the user wants to use this model to send transactions calling the contract functions. * - **Provider**: when the user wants to use this model to get information from the contracts or subgraph. * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example + * @example * - * ### Signer + * ###Using Signer * - * **Using private key (backend)** + * ####Using private key (backend) * * ```ts * import { StakingClient } from '@human-protocol/sdk'; - * import { Wallet, providers } from 'ethers'; + * import { Wallet, JsonRpcProvider } from 'ethers'; * * const rpcUrl = 'YOUR_RPC_URL'; * const privateKey = 'YOUR_PRIVATE_KEY'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); + * const provider = new JsonRpcProvider(rpcUrl); * const signer = new Wallet(privateKey, provider); * const stakingClient = await StakingClient.build(signer); * ``` * - * **Using Wagmi (frontend)** + * ####Using Wagmi (frontend) * * ```ts * import { useSigner, useChainId } from 'wagmi'; @@ -93,15 +79,15 @@ import { * const stakingClient = await StakingClient.build(signer); * ``` * - * ### Provider + * ###Using Provider * * ```ts * import { StakingClient } from '@human-protocol/sdk'; - * import { providers } from 'ethers'; + * import { JsonRpcProvider } from 'ethers'; * * const rpcUrl = 'YOUR_RPC_URL'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); + * const provider = new JsonRpcProvider(rpcUrl); * const stakingClient = await StakingClient.build(provider); * ``` */ @@ -113,8 +99,8 @@ export class StakingClient extends BaseEthersClient { /** * **StakingClient constructor** * - * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network - * @param {NetworkData} networkData - The network information required to connect to the Staking contract + * @param runner - The Runner object to interact with the Ethereum network + * @param networkData - The network information required to connect to the Staking contract */ constructor(runner: ContractRunner, networkData: NetworkData) { super(runner, networkData); @@ -138,11 +124,23 @@ export class StakingClient extends BaseEthersClient { /** * Creates an instance of StakingClient from a Runner. * - * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network + * @param runner - The Runner object to interact with the Ethereum network + * @returns An instance of StakingClient + * @throws ErrorProviderDoesNotExist If the provider does not exist for the provided Signer + * @throws ErrorUnsupportedChainID If the network's chainId is not supported * - * @returns {Promise} - An instance of StakingClient - * @throws {ErrorProviderDoesNotExist} - Thrown if the provider does not exist for the provided Signer - * @throws {ErrorUnsupportedChainID} - Thrown if the network's chainId is not supported + * @example + * ```ts + * import { StakingClient } from '@human-protocol/sdk'; + * import { Wallet, JsonRpcProvider } from 'ethers'; + * + * const rpcUrl = 'YOUR_RPC_URL'; + * const privateKey = 'YOUR_PRIVATE_KEY'; + * + * const provider = new JsonRpcProvider(rpcUrl); + * const signer = new Wallet(privateKey, provider); + * const stakingClient = await StakingClient.build(signer); + * ``` */ public static async build(runner: ContractRunner): Promise { if (!runner.provider) { @@ -179,24 +177,17 @@ export class StakingClient extends BaseEthersClient { /** * This function approves the staking contract to transfer a specified amount of tokens when the user stakes. It increases the allowance for the staking contract. * - * @param {bigint} amount Amount in WEI of tokens to approve for stake. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * **Code example** + * @param amount - Amount in WEI of tokens to approve for stake. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidStakingValueType If the amount is not a bigint + * @throws ErrorInvalidStakingValueSign If the amount is negative * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; + * import { ethers } from 'ethers'; * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * - * const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI + * const amount = ethers.parseUnits('5', 'ether'); //convert from ETH to WEI * await stakingClient.approveStake(amount); * ``` */ @@ -230,26 +221,20 @@ export class StakingClient extends BaseEthersClient { /** * This function stakes a specified amount of tokens on a specific network. * - * > `approveStake` must be called before - * - * @param {bigint} amount Amount in WEI of tokens to stake. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. + * !!! note + * `approveStake` must be called before * - * **Code example** + * @param amount - Amount in WEI of tokens to stake. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidStakingValueType If the amount is not a bigint + * @throws ErrorInvalidStakingValueSign If the amount is negative * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; + * import { ethers } from 'ethers'; * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * - * const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI + * const amount = ethers.parseUnits('5', 'ether'); //convert from ETH to WEI * await stakingClient.approveStake(amount); // if it was already approved before, this is not necessary * await stakingClient.stake(amount); * ``` @@ -275,26 +260,20 @@ export class StakingClient extends BaseEthersClient { /** * This function unstakes tokens from staking contract. The unstaked tokens stay locked for a period of time. * - * > Must have tokens available to unstake - * - * @param {bigint} amount Amount in WEI of tokens to unstake. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. + * !!! note + * Must have tokens available to unstake * - * **Code example** + * @param amount - Amount in WEI of tokens to unstake. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidStakingValueType If the amount is not a bigint + * @throws ErrorInvalidStakingValueSign If the amount is negative * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); + * import { ethers } from 'ethers'; * - * const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI + * const amount = ethers.parseUnits('5', 'ether'); //convert from ETH to WEI * await stakingClient.unstake(amount); * ``` */ @@ -321,25 +300,14 @@ export class StakingClient extends BaseEthersClient { /** * This function withdraws unstaked and non-locked tokens from staking contract to the user wallet. + * !!! note + * Must have tokens available to withdraw * - * > Must have tokens available to withdraw - * - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * **Code example** + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - * + * @example * ```ts - * import { Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * * await stakingClient.withdraw(); * ``` */ @@ -356,28 +324,30 @@ export class StakingClient extends BaseEthersClient { /** * This function reduces the allocated amount by a staker in an escrow and transfers those tokens to the reward pool. This allows the slasher to claim them later. * - * @param {string} slasher Wallet address from who requested the slash - * @param {string} staker Wallet address from who is going to be slashed - * @param {string} escrowAddress Address of the escrow that the slash is made - * @param {bigint} amount Amount in WEI of tokens to slash. - * @param {Overrides} [txOptions] - Additional transaction parameters (optional, defaults to an empty object). - * @returns Returns void if successful. Throws error if any. - * - * **Code example** - * + * @param slasher - Wallet address from who requested the slash + * @param staker - Wallet address from who is going to be slashed + * @param escrowAddress - Address of the escrow that the slash is made + * @param amount - Amount in WEI of tokens to slash. + * @param txOptions - Additional transaction parameters (optional, defaults to an empty object). + * @returns - + * @throws ErrorInvalidStakingValueType If the amount is not a bigint + * @throws ErrorInvalidStakingValueSign If the amount is negative + * @throws ErrorInvalidSlasherAddressProvided If the slasher address is invalid + * @throws ErrorInvalidStakerAddressProvided If the staker address is invalid + * @throws ErrorInvalidEscrowAddressProvided If the escrow address is invalid + * @throws ErrorEscrowAddressIsNotProvidedByFactory If the escrow is not provided by the factory + * + * @example * ```ts - * import { ethers, Wallet, providers } from 'ethers'; - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * const privateKey = 'YOUR_PRIVATE_KEY'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const signer = new Wallet(privateKey, provider); - * const stakingClient = await StakingClient.build(signer); - * - * const amount = ethers.parseUnits(5, 'ether'); //convert from ETH to WEI - * await stakingClient.slash('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', '0x62dD51230A30401C455c8398d06F85e4EaB6309f', amount); + * import { ethers } from 'ethers'; + * + * const amount = ethers.parseUnits('5', 'ether'); //convert from ETH to WEI + * await stakingClient.slash( + * '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', + * '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f', + * amount + * ); * ``` */ @requiresSigner @@ -426,21 +396,14 @@ export class StakingClient extends BaseEthersClient { /** * Retrieves comprehensive staking information for a staker. * - * @param {string} stakerAddress - The address of the staker. - * @returns {Promise} - * - * **Code example** + * @param stakerAddress - The address of the staker. + * @returns Staking information for the staker + * @throws ErrorInvalidStakerAddressProvided If the staker address is invalid * + * @example * ```ts - * import { StakingClient } from '@human-protocol/sdk'; - * - * const rpcUrl = 'YOUR_RPC_URL'; - * - * const provider = new providers.JsonRpcProvider(rpcUrl); - * const stakingClient = await StakingClient.build(provider); - * * const stakingInfo = await stakingClient.getStakerInfo('0xYourStakerAddress'); - * console.log(stakingInfo.tokensStaked); + * console.log('Tokens staked:', stakingInfo.stakedAmount); * ``` */ public async getStakerInfo(stakerAddress: string): Promise { @@ -479,16 +442,41 @@ export class StakingClient extends BaseEthersClient { } /** - * Utility class for Staking-related subgraph queries. + * Utility helpers for Staking-related queries. + * + * @example + * ```ts + * import { StakingUtils, ChainId } from '@human-protocol/sdk'; + * + * const staker = await StakingUtils.getStaker( + * ChainId.POLYGON_AMOY, + * '0xYourStakerAddress' + * ); + * console.log('Staked amount:', staker.stakedAmount); + * ``` */ export class StakingUtils { /** * Gets staking info for a staker from the subgraph. * - * @param {ChainId} chainId Network in which the staking contract is deployed - * @param {string} stakerAddress Address of the staker - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Staker info from subgraph + * @param chainId - Network in which the staking contract is deployed + * @param stakerAddress - Address of the staker + * @param options - Optional configuration for subgraph requests. + * @returns Staker info from subgraph + * @throws ErrorInvalidStakerAddressProvided If the staker address is invalid + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorStakerNotFound If the staker is not found + * + * @example + * ```ts + * import { StakingUtils, ChainId } from '@human-protocol/sdk'; + * + * const staker = await StakingUtils.getStaker( + * ChainId.POLYGON_AMOY, + * '0xYourStakerAddress' + * ); + * console.log('Staked amount:', staker.stakedAmount); + * ``` */ public static async getStaker( chainId: ChainId, @@ -521,9 +509,22 @@ export class StakingUtils { /** * Gets all stakers from the subgraph with filters, pagination and ordering. * - * @param {IStakersFilter} filter Stakers filter with pagination and ordering - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Array of stakers + * @param filter - Stakers filter with pagination and ordering + * @param options - Optional configuration for subgraph requests. + * @returns Array of stakers + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * + * @example + * ```ts + * import { ChainId } from '@human-protocol/sdk'; + * + * const filter = { + * chainId: ChainId.POLYGON_AMOY, + * minStakedAmount: '1000000000000000000', // 1 token in WEI + * }; + * const stakers = await StakingUtils.getStakers(filter); + * console.log('Stakers:', stakers.length); + * ``` */ public static async getStakers( filter: IStakersFilter, diff --git a/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts b/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts index 36095e7258..fd1192a449 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/statistics.ts @@ -30,51 +30,21 @@ import { } from './utils'; /** - * ## Introduction + * Utility class for statistics-related queries. * - * This client enables obtaining statistical information from the subgraph. - * - * Unlike other SDK clients, `StatisticsClient` does not require `signer` or `provider` to be provided. - * We just need to create a client object using relevant network data. - * - * ```ts - * constructor(network: NetworkData) - * ``` - * - * ## Installation - * - * ### npm - * ```bash - * npm install @human-protocol/sdk - * ``` - * - * ### yarn - * ```bash - * yarn install @human-protocol/sdk - * ``` - * - * ## Code example + * Unlike other SDK clients, `StatisticsUtils` does not require `signer` or `provider` to be provided. + * We just need to pass the network data to each static method. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const escrowStats = await StatisticsUtils.getEscrowStatistics(networkData); + * console.log('Total escrows:', escrowStats.totalEscrows); * ``` */ -export class StatisticsClient { - public networkData: NetworkData; - public subgraphUrl: string; - - /** - * **StatisticsClient constructor** - * - * @param {NetworkData} networkData - The network information required to connect to the Statistics contract - */ - constructor(networkData: NetworkData) { - this.networkData = networkData; - this.subgraphUrl = getSubgraphUrl(networkData); - } - +export class StatisticsUtils { /** * This function returns the statistical data of escrows. * @@ -106,29 +76,36 @@ export class StatisticsClient { * }; * ``` * - * @param {IStatisticsFilter} filter Statistics params with duration data - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Escrow statistics data. - * - * **Code example** + * @param networkData - The network information required to connect to the subgraph + * @param filter - Statistics params with duration data + * @param options - Optional configuration for subgraph requests. + * @returns Escrow statistics data. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - * - * const escrowStatistics = await statisticsClient.getEscrowStatistics(); - * const escrowStatisticsApril = await statisticsClient.getEscrowStatistics({ - * from: new Date('2021-04-01'), - * to: new Date('2021-04-30'), - * }); + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; + * + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const escrowStats = await StatisticsUtils.getEscrowStatistics(networkData); + * console.log('Total escrows:', escrowStats.totalEscrows); + * + * const escrowStatsApril = await StatisticsUtils.getEscrowStatistics( + * networkData, + * { + * from: new Date('2021-04-01'), + * to: new Date('2021-04-30'), + * } + * ); + * console.log('April escrows:', escrowStatsApril.totalEscrows); * ``` */ - async getEscrowStatistics( + static async getEscrowStatistics( + networkData: NetworkData, filter: IStatisticsFilter = {}, options?: SubgraphOptions ): Promise { try { + const subgraphUrl = getSubgraphUrl(networkData); const first = filter.first !== undefined ? Math.min(filter.first, 1000) : 10; const skip = filter.skip || 0; @@ -136,12 +113,12 @@ export class StatisticsClient { const { escrowStatistics } = await customGqlFetch<{ escrowStatistics: EscrowStatisticsData; - }>(this.subgraphUrl, GET_ESCROW_STATISTICS_QUERY, options); + }>(subgraphUrl, GET_ESCROW_STATISTICS_QUERY, options); const { eventDayDatas } = await customGqlFetch<{ eventDayDatas: EventDayData[]; }>( - this.subgraphUrl, + subgraphUrl, GET_EVENT_DAY_DATA_QUERY(filter), { from: filter.from ? getUnixTimestamp(filter.from) : undefined, @@ -197,29 +174,36 @@ export class StatisticsClient { * }; * ``` * - * @param {IStatisticsFilter} filter Statistics params with duration data - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Worker statistics data. - * - * **Code example** + * @param networkData - The network information required to connect to the subgraph + * @param filter - Statistics params with duration data + * @param options - Optional configuration for subgraph requests. + * @returns Worker statistics data. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - * - * const workerStatistics = await statisticsClient.getWorkerStatistics(); - * const workerStatisticsApril = await statisticsClient.getWorkerStatistics({ - * from: new Date('2021-04-01'), - * to: new Date('2021-04-30'), - * }); + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; + * + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const workerStats = await StatisticsUtils.getWorkerStatistics(networkData); + * console.log('Daily workers data:', workerStats.dailyWorkersData); + * + * const workerStatsApril = await StatisticsUtils.getWorkerStatistics( + * networkData, + * { + * from: new Date('2021-04-01'), + * to: new Date('2021-04-30'), + * } + * ); + * console.log('April workers:', workerStatsApril.dailyWorkersData.length); * ``` */ - async getWorkerStatistics( + static async getWorkerStatistics( + networkData: NetworkData, filter: IStatisticsFilter = {}, options?: SubgraphOptions ): Promise { try { + const subgraphUrl = getSubgraphUrl(networkData); const first = filter.first !== undefined ? Math.min(filter.first, 1000) : 10; const skip = filter.skip || 0; @@ -228,7 +212,7 @@ export class StatisticsClient { const { eventDayDatas } = await customGqlFetch<{ eventDayDatas: EventDayData[]; }>( - this.subgraphUrl, + subgraphUrl, GET_EVENT_DAY_DATA_QUERY(filter), { from: filter.from ? getUnixTimestamp(filter.from) : undefined, @@ -279,50 +263,43 @@ export class StatisticsClient { * }; * ``` * - * @param {IStatisticsFilter} filter Statistics params with duration data - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Payment statistics data. - * - * **Code example** + * @param networkData - The network information required to connect to the subgraph + * @param filter - Statistics params with duration data + * @param options - Optional configuration for subgraph requests. + * @returns Payment statistics data. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; * + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const paymentStats = await StatisticsUtils.getPaymentStatistics(networkData); * console.log( * 'Payment statistics:', - * (await statisticsClient.getPaymentStatistics()).dailyPaymentsData.map( - * (p) => ({ - * ...p, - * totalAmountPaid: p.totalAmountPaid.toString(), - * averageAmountPerJob: p.averageAmountPerJob.toString(), - * averageAmountPerWorker: p.averageAmountPerWorker.toString(), - * }) - * ) - * ); - * - * console.log( - * 'Payment statistics from 5/8 - 6/8:', - * ( - * await statisticsClient.getPaymentStatistics({ - * from: new Date(2023, 4, 8), - * to: new Date(2023, 5, 8), - * }) - * ).dailyPaymentsData.map((p) => ({ + * paymentStats.dailyPaymentsData.map((p) => ({ * ...p, * totalAmountPaid: p.totalAmountPaid.toString(), - * averageAmountPerJob: p.averageAmountPerJob.toString(), * averageAmountPerWorker: p.averageAmountPerWorker.toString(), * })) * ); + * + * const paymentStatsRange = await StatisticsUtils.getPaymentStatistics( + * networkData, + * { + * from: new Date(2023, 4, 8), + * to: new Date(2023, 5, 8), + * } + * ); + * console.log('Payment statistics from 5/8 - 6/8:', paymentStatsRange.dailyPaymentsData.length); * ``` */ - async getPaymentStatistics( + static async getPaymentStatistics( + networkData: NetworkData, filter: IStatisticsFilter = {}, options?: SubgraphOptions ): Promise { try { + const subgraphUrl = getSubgraphUrl(networkData); const first = filter.first !== undefined ? Math.min(filter.first, 1000) : 10; const skip = filter.skip || 0; @@ -331,7 +308,7 @@ export class StatisticsClient { const { eventDayDatas } = await customGqlFetch<{ eventDayDatas: EventDayData[]; }>( - this.subgraphUrl, + subgraphUrl, GET_EVENT_DAY_DATA_QUERY(filter), { from: filter.from ? getUnixTimestamp(filter.from) : undefined, @@ -371,29 +348,31 @@ export class StatisticsClient { * }; * ``` * - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} HMToken statistics data. - * - * **Code example** + * @param networkData - The network information required to connect to the subgraph + * @param options - Optional configuration for subgraph requests. + * @returns HMToken statistics data. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - * - * const hmtStatistics = await statisticsClient.getHMTStatistics(); + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; * + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const hmtStats = await StatisticsUtils.getHMTStatistics(networkData); * console.log('HMT statistics:', { - * ...hmtStatistics, - * totalTransferAmount: hmtStatistics.totalTransferAmount.toString(), + * ...hmtStats, + * totalTransferAmount: hmtStats.totalTransferAmount.toString(), * }); * ``` */ - async getHMTStatistics(options?: SubgraphOptions): Promise { + static async getHMTStatistics( + networkData: NetworkData, + options?: SubgraphOptions + ): Promise { try { + const subgraphUrl = getSubgraphUrl(networkData); const { hmtokenStatistics } = await customGqlFetch<{ hmtokenStatistics: HMTStatisticsData; - }>(this.subgraphUrl, GET_HMTOKEN_STATISTICS_QUERY, options); + }>(subgraphUrl, GET_HMTOKEN_STATISTICS_QUERY, options); return { totalTransferAmount: BigInt(hmtokenStatistics.totalValueTransfered), @@ -408,39 +387,37 @@ export class StatisticsClient { /** * This function returns the holders of the HMToken with optional filters and ordering. * - * **Input parameters** - * - * @param {IHMTHoldersParams} params HMT Holders params with filters and ordering - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} List of HMToken holders. - * - * **Code example** + * @param networkData - The network information required to connect to the subgraph + * @param params - HMT Holders params with filters and ordering + * @param options - Optional configuration for subgraph requests. + * @returns List of HMToken holders. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; * - * const hmtHolders = await statisticsClient.getHMTHolders({ + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const hmtHolders = await StatisticsUtils.getHMTHolders(networkData, { * orderDirection: 'asc', * }); - * * console.log('HMT holders:', hmtHolders.map((h) => ({ * ...h, * balance: h.balance.toString(), * }))); * ``` */ - async getHMTHolders( + static async getHMTHolders( + networkData: NetworkData, params: IHMTHoldersParams = {}, options?: SubgraphOptions ): Promise { try { + const subgraphUrl = getSubgraphUrl(networkData); const { address, orderDirection } = params; const query = GET_HOLDERS_QUERY(address); const { holders } = await customGqlFetch<{ holders: HMTHolderData[] }>( - this.subgraphUrl, + subgraphUrl, query, { address, @@ -484,34 +461,36 @@ export class StatisticsClient { * } * ``` * - * @param {IStatisticsFilter} filter Statistics params with duration data - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Daily HMToken statistics data. - * - * **Code example** + * @param networkData - The network information required to connect to the subgraph + * @param filter - Statistics params with duration data + * @param options - Optional configuration for subgraph requests. + * @returns Daily HMToken statistics data. * + * @example * ```ts - * import { StatisticsClient, ChainId, NETWORKS } from '@human-protocol/sdk'; - * - * const statisticsClient = new StatisticsClient(NETWORKS[ChainId.POLYGON_AMOY]); - * - * const dailyHMTStats = await statisticsClient.getHMTStatistics(); + * import { StatisticsUtils, ChainId, NETWORKS } from '@human-protocol/sdk'; * + * const networkData = NETWORKS[ChainId.POLYGON_AMOY]; + * const dailyHMTStats = await StatisticsUtils.getHMTDailyData(networkData); * console.log('Daily HMT statistics:', dailyHMTStats); * - * const hmtStatisticsRange = await statisticsClient.getHMTStatistics({ - * from: new Date(2023, 4, 8), - * to: new Date(2023, 5, 8), - * }); - * - * console.log('HMT statistics from 5/8 - 6/8:', hmtStatisticsRange); + * const hmtStatsRange = await StatisticsUtils.getHMTDailyData( + * networkData, + * { + * from: new Date(2023, 4, 8), + * to: new Date(2023, 5, 8), + * } + * ); + * console.log('HMT statistics from 5/8 - 6/8:', hmtStatsRange.length); * ``` */ - async getHMTDailyData( + static async getHMTDailyData( + networkData: NetworkData, filter: IStatisticsFilter = {}, options?: SubgraphOptions ): Promise { try { + const subgraphUrl = getSubgraphUrl(networkData); const first = filter.first !== undefined ? Math.min(filter.first, 1000) : 10; const skip = filter.skip || 0; @@ -520,7 +499,7 @@ export class StatisticsClient { const { eventDayDatas } = await customGqlFetch<{ eventDayDatas: EventDayData[]; }>( - this.subgraphUrl, + subgraphUrl, GET_EVENT_DAY_DATA_QUERY(filter), { from: filter.from ? getUnixTimestamp(filter.from) : undefined, diff --git a/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts b/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts index dc792ce6d2..6359018653 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/transaction.ts @@ -19,6 +19,20 @@ import { } from './interfaces'; import { getSubgraphUrl, getUnixTimestamp, customGqlFetch } from './utils'; +/** + * Utility class for transaction-related queries. + * + * @example + * ```ts + * import { TransactionUtils, ChainId } from '@human-protocol/sdk'; + * + * const transaction = await TransactionUtils.getTransaction( + * ChainId.POLYGON_AMOY, + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + * ); + * console.log('Transaction:', transaction); + * ``` + */ export class TransactionUtils { /** * This function returns the transaction data for the given hash. @@ -51,17 +65,22 @@ export class TransactionUtils { * }; * ``` * - * @param {ChainId} chainId The chain ID. - * @param {string} hash The transaction hash. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} - Returns the transaction details or null if not found. - * - * **Code example** + * @param chainId - The chain ID. + * @param hash - The transaction hash. + * @param options - Optional configuration for subgraph requests. + * @returns Returns the transaction details or null if not found. + * @throws ErrorInvalidHashProvided If the hash is invalid + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts * import { TransactionUtils, ChainId } from '@human-protocol/sdk'; * - * const transaction = await TransactionUtils.getTransaction(ChainId.POLYGON, '0x62dD51230A30401C455c8398d06F85e4EaB6309f'); + * const transaction = await TransactionUtils.getTransaction( + * ChainId.POLYGON_AMOY, + * '0x62dD51230A30401C455c8398d06F85e4EaB6309f' + * ); + * console.log('Transaction:', transaction); * ``` */ public static async getTransaction( @@ -116,7 +135,7 @@ export class TransactionUtils { * skip?: number; // (Optional) Number of transactions to skip. Default is 0. * orderDirection?: OrderDirection; // (Optional) Order of the results. Default is DESC. * } - * + * ``` * * ```ts * type InternalTransaction = { @@ -146,17 +165,18 @@ export class TransactionUtils { * }; * ``` * - * @param {ITransactionsFilter} filter Filter for the transactions. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Returns an array with all the transaction details. - * - * **Code example** + * @param filter - Filter for the transactions. + * @param options - Optional configuration for subgraph requests. + * @returns Returns an array with all the transaction details. + * @throws ErrorCannotUseDateAndBlockSimultaneously If both date and block filters are used + * @throws ErrorUnsupportedChainID If the chain ID is not supported * + * @example * ```ts * import { TransactionUtils, ChainId, OrderDirection } from '@human-protocol/sdk'; * - * const filter: ITransactionsFilter = { - * chainId: ChainId.POLYGON, + * const filter = { + * chainId: ChainId.POLYGON_AMOY, * startDate: new Date('2022-01-01'), * endDate: new Date('2022-12-31'), * first: 10, @@ -164,6 +184,7 @@ export class TransactionUtils { * orderDirection: OrderDirection.DESC, * }; * const transactions = await TransactionUtils.getTransactions(filter); + * console.log('Transactions:', transactions.length); * ``` */ public static async getTransactions( diff --git a/packages/sdk/typescript/human-protocol-sdk/src/utils.ts b/packages/sdk/typescript/human-protocol-sdk/src/utils.ts index f7ef8d8fb0..ce0f45ff6d 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/utils.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/utils.ts @@ -21,10 +21,16 @@ import { NetworkData } from './types'; import { SubgraphOptions } from './interfaces'; /** - * **Handle and throw the error.* + * Handles and throws appropriate error types based on the Ethereum error. * - * @param {any} e - * @returns + * @param e - The error to handle + * @throws {InvalidArgumentError} If the error is an invalid argument error + * @throws {ContractExecutionError} If the error is a contract execution error + * @throws {TransactionReplaced} If the transaction was replaced + * @throws {ReplacementUnderpriced} If the replacement transaction was underpriced + * @throws {NumericFault} If there's a numeric fault + * @throws {NonceExpired} If the nonce has expired + * @throws {EthereumError} For any other Ethereum-related error */ export const throwError = (e: any) => { if (ethers.isError(e, 'INVALID_ARGUMENT')) { @@ -45,10 +51,10 @@ export const throwError = (e: any) => { }; /** - * **URL validation.* + * Validates if a string is a valid URL. * - * @param {string} url - * @returns + * @param url - The URL string to validate + * @returns True if the URL is valid, false otherwise */ export const isValidUrl = (url: string): boolean => { return isURL(url, { @@ -59,10 +65,10 @@ export const isValidUrl = (url: string): boolean => { }; /** - * **Check if a string is a valid JSON.* + * Checks if a string is valid JSON. * - * @param {string} input - * @returns {boolean} + * @param input - The string to check + * @returns True if the string is valid JSON, false otherwise */ export const isValidJson = (input: string): boolean => { try { @@ -74,10 +80,10 @@ export const isValidJson = (input: string): boolean => { }; /** - * **Get the subgraph URL.* + * Gets the subgraph URL for the given network, using API key if available. * - * @param {NetworkData} networkData - * @returns + * @param networkData - The network data containing subgraph URLs + * @returns The subgraph URL with API key if available */ export const getSubgraphUrl = (networkData: NetworkData) => { let subgraphUrl = networkData.subgraphUrl; @@ -95,10 +101,10 @@ export const getSubgraphUrl = (networkData: NetworkData) => { }; /** - * **Convert a date to Unix timestamp (seconds since epoch).* + * Converts a Date object to Unix timestamp (seconds since epoch). * - * @param {Date} date - * @returns {number} + * @param date - The date to convert + * @returns Unix timestamp in seconds */ export const getUnixTimestamp = (date: Date): number => { return Math.floor(date.getTime() / 1000); @@ -127,8 +133,16 @@ const buildIndexerUrl = (baseUrl: string, indexerId?: string): string => { }; /** - * Execute a GraphQL request with automatic retry logic for bad indexer errors. - * Only retries if options is provided. + * Executes a GraphQL request with automatic retry logic for bad indexer errors. + * Only retries if options is provided with maxRetries and baseDelay. + * + * @param url - The GraphQL endpoint URL + * @param query - The GraphQL query to execute + * @param variables - Variables for the GraphQL query (optional) + * @param options - Optional configuration for subgraph requests including retry logic + * @returns The response data from the GraphQL query + * @throws ErrorRetryParametersMissing If only one of maxRetries or baseDelay is provided + * @throws ErrorRoutingRequestsToIndexerRequiresApiKey If indexerId is provided without API key */ export const customGqlFetch = async ( url: string, diff --git a/packages/sdk/typescript/human-protocol-sdk/src/worker.ts b/packages/sdk/typescript/human-protocol-sdk/src/worker.ts index 6d37ec10bc..e76278bd3b 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/worker.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/worker.ts @@ -7,21 +7,40 @@ import { GET_WORKER_QUERY, GET_WORKERS_QUERY } from './graphql/queries/worker'; import { IWorker, IWorkersFilter, SubgraphOptions } from './interfaces'; import { getSubgraphUrl, customGqlFetch } from './utils'; +/** + * Utility class for worker-related operations. + * + * @example + * ```ts + * import { WorkerUtils, ChainId } from '@human-protocol/sdk'; + * + * const worker = await WorkerUtils.getWorker( + * ChainId.POLYGON_AMOY, + * '0x1234567890abcdef1234567890abcdef12345678' + * ); + * console.log('Worker:', worker); + * ``` + */ export class WorkerUtils { /** * This function returns the worker data for the given address. * - * @param {ChainId} chainId The chain ID. - * @param {string} address The worker address. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} - Returns the worker details or null if not found. - * - * **Code example** + * @param chainId - The chain ID. + * @param address - The worker address. + * @param options - Optional configuration for subgraph requests. + * @returns Returns the worker details or null if not found. + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorInvalidAddress If the address is invalid * + * @example * ```ts * import { WorkerUtils, ChainId } from '@human-protocol/sdk'; * - * const worker = await WorkerUtils.getWorker(ChainId.POLYGON, '0x1234567890abcdef1234567890abcdef12345678'); + * const worker = await WorkerUtils.getWorker( + * ChainId.POLYGON_AMOY, + * '0x1234567890abcdef1234567890abcdef12345678' + * ); + * console.log('Worker:', worker); * ``` */ public static async getWorker( @@ -79,21 +98,23 @@ export class WorkerUtils { * }; * ``` * - * @param {IWorkersFilter} filter Filter for the workers. - * @param {SubgraphOptions} options Optional configuration for subgraph requests. - * @returns {Promise} Returns an array with all the worker details. - * - * **Code example** + * @param filter - Filter for the workers. + * @param options - Optional configuration for subgraph requests. + * @returns Returns an array with all the worker details. + * @throws ErrorUnsupportedChainID If the chain ID is not supported + * @throws ErrorInvalidAddress If the filter address is invalid * + * @example * ```ts * import { WorkerUtils, ChainId } from '@human-protocol/sdk'; * - * const filter: IWorkersFilter = { - * chainId: ChainId.POLYGON, + * const filter = { + * chainId: ChainId.POLYGON_AMOY, * first: 10, * skip: 0, * }; * const workers = await WorkerUtils.getWorkers(filter); + * console.log('Workers:', workers.length); * ``` */ public static async getWorkers( diff --git a/packages/sdk/typescript/human-protocol-sdk/tsconfig.eslint.json b/packages/sdk/typescript/human-protocol-sdk/tsconfig.eslint.json index 1f7243e15a..653985b892 100644 --- a/packages/sdk/typescript/human-protocol-sdk/tsconfig.eslint.json +++ b/packages/sdk/typescript/human-protocol-sdk/tsconfig.eslint.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "include": ["src", "test", "example", "vitest.config.ts"] + "include": ["src", "test", "example", "vitest.config.ts", "scripts"], } diff --git a/packages/sdk/typescript/human-protocol-sdk/typedoc.json b/packages/sdk/typescript/human-protocol-sdk/typedoc.json new file mode 100644 index 0000000000..36912e847b --- /dev/null +++ b/packages/sdk/typescript/human-protocol-sdk/typedoc.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://typedoc-plugin-markdown.org/schema.json", + "entryPoints": [ + "src/index.ts" + ], + "entryPointStrategy": "expand", + "out": "docs", + "plugin": [ + "typedoc-plugin-markdown" + ], + "readme": "none", + "cleanOutputDir": false, + "excludePrivate": true, + "excludeInternal": true, + "excludeProtected": false, + "excludeExternals": false, + "excludeNotDocumented": true, + "categorizeByGroup": false, + "mergeReadme": false, + "blockTags": [ + "@param", + "@returns", + "@throws", + "@example", + "@remarks" + ], + "parametersFormat": "table", + "classPropertiesFormat": "table", + "interfacePropertiesFormat": "table", + "propertyMembersFormat": "table", + "enumMembersFormat": "table", + "typeDeclarationFormat": "table", + "useCodeBlocks": true, + "expandParameters": true, + "hidePageHeader": true, + "hidePageTitle": true, + "hideBreadcrumbs": true, + "disableSources": true, + "excludeTags": [ + "@overload" + ], + "sort": [ + "source-order" + ], + "includeVersion": true +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 3dbb7dc88a..f61c68eb90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4371,16 +4371,16 @@ __metadata: languageName: node linkType: hard -"@gerrit0/mini-shiki@npm:^3.12.0": - version: 3.14.0 - resolution: "@gerrit0/mini-shiki@npm:3.14.0" - dependencies: - "@shikijs/engine-oniguruma": "npm:^3.14.0" - "@shikijs/langs": "npm:^3.14.0" - "@shikijs/themes": "npm:^3.14.0" - "@shikijs/types": "npm:^3.14.0" +"@gerrit0/mini-shiki@npm:^3.17.0": + version: 3.19.0 + resolution: "@gerrit0/mini-shiki@npm:3.19.0" + dependencies: + "@shikijs/engine-oniguruma": "npm:^3.19.0" + "@shikijs/langs": "npm:^3.19.0" + "@shikijs/themes": "npm:^3.19.0" + "@shikijs/types": "npm:^3.19.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/9539688aec140f2167203b424078d34deec016c8418c497146c6c24920d0590d10b2cd5eec721668a56cb5d42fb278f6f0502bc340274398bb690317ded563b2 + checksum: 10c0/671b4dedbec6702a6ac11ef10091f596f4e63447127d7ed552d8401acfe6a97f2bd983de788739e3544a2fe4b6bc45395618ad3e7c39c9961f32a489b6fae654 languageName: node linkType: hard @@ -4986,6 +4986,7 @@ __metadata: eslint-plugin-jest: "npm:^28.9.0" eslint-plugin-prettier: "npm:^5.2.1" ethers: "npm:~6.15.0" + glob: "npm:^13.0.0" graphql: "npm:^16.8.1" graphql-request: "npm:^7.3.4" graphql-tag: "npm:^2.12.6" @@ -4993,8 +4994,8 @@ __metadata: prettier: "npm:^3.7.4" secp256k1: "npm:^5.0.1" ts-node: "npm:^10.9.2" - typedoc: "npm:^0.28.7" - typedoc-plugin-markdown: "npm:^4.2.3" + typedoc: "npm:^0.28.15" + typedoc-plugin-markdown: "npm:^4.9.0" typescript: "npm:^5.8.3" validator: "npm:^13.12.0" vitest: "npm:^3.0.9" @@ -9056,41 +9057,41 @@ __metadata: languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:^3.14.0": - version: 3.14.0 - resolution: "@shikijs/engine-oniguruma@npm:3.14.0" +"@shikijs/engine-oniguruma@npm:^3.19.0": + version: 3.19.0 + resolution: "@shikijs/engine-oniguruma@npm:3.19.0" dependencies: - "@shikijs/types": "npm:3.14.0" + "@shikijs/types": "npm:3.19.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/6dab2310c910fedd89046299c4423b2100c8c771822e487070d9eb158907782f195f1b9dd560b6b84f74432bdd1ca4e4429f4af76d30c0e45f8448f100094996 + checksum: 10c0/6f2cbc08c39af982ae3b75283c8216d1932e894a7a1318490807b383ef5f658b1b2940dbab760dfe1b8647ba8df7a365d89e16b02f4f51e397f22046df4b4b5d languageName: node linkType: hard -"@shikijs/langs@npm:^3.14.0": - version: 3.14.0 - resolution: "@shikijs/langs@npm:3.14.0" +"@shikijs/langs@npm:^3.19.0": + version: 3.19.0 + resolution: "@shikijs/langs@npm:3.19.0" dependencies: - "@shikijs/types": "npm:3.14.0" - checksum: 10c0/59ed3b0e9f893a57c8e88b77e9280d993b0dfe219b91db2f8143a65728ef47b02e17056a029f710753184e1c077dfa589cbc5491253d791472a94dca9f598fa3 + "@shikijs/types": "npm:3.19.0" + checksum: 10c0/a7e69ed7c1cea2ccf412a149bd9c4327b6d9314b03271f9782b1703d61949e9787a05d1265f8590c8aa3641657709661c719d105100e70b35a6490c443ceac19 languageName: node linkType: hard -"@shikijs/themes@npm:^3.14.0": - version: 3.14.0 - resolution: "@shikijs/themes@npm:3.14.0" +"@shikijs/themes@npm:^3.19.0": + version: 3.19.0 + resolution: "@shikijs/themes@npm:3.19.0" dependencies: - "@shikijs/types": "npm:3.14.0" - checksum: 10c0/3326482f081e313957c3e74ae86721d18efb32c022b31936f7da1b4782f4c970dea71989934baf9ab8adbeafea07235834b2e6ab83b67e71dc87fb328a1caa58 + "@shikijs/types": "npm:3.19.0" + checksum: 10c0/504d7f637bf5555314bc4a3a61c8cc4f3c712cc00d807f12a40a9d144d40f722dbc0e42409f2a83996cfb2c072326a48e237c265c048b6991844b166f607036b languageName: node linkType: hard -"@shikijs/types@npm:3.14.0, @shikijs/types@npm:^3.14.0": - version: 3.14.0 - resolution: "@shikijs/types@npm:3.14.0" +"@shikijs/types@npm:3.19.0, @shikijs/types@npm:^3.19.0": + version: 3.19.0 + resolution: "@shikijs/types@npm:3.19.0" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10c0/154ec7a79e3c155ed47a14d14ccf91ea09909779993f999cf3d7e424c2f732cd7d7faf8074441a543445f64af1ef9456dcf9ddd4edad96615b68ca60eca2b7bc + checksum: 10c0/fc6509e282c257e4b614d5da3e1e99c7d2e6d4fef6ade3afa668b30dee6763035ad98fadace14f97021cdb371a70eed5ae46cde87f7794fe95e098d6d8a46a3f languageName: node linkType: hard @@ -19826,6 +19827,17 @@ __metadata: languageName: node linkType: hard +"glob@npm:^13.0.0": + version: 13.0.0 + resolution: "glob@npm:13.0.0" + dependencies: + minimatch: "npm:^10.1.1" + minipass: "npm:^7.1.2" + path-scurry: "npm:^2.0.0" + checksum: 10c0/8e2f5821f3f7c312dd102e23a15b80c79e0837a9872784293ba2e15ec73b3f3749a49a42a31bfcb4e52c84820a474e92331c2eebf18819d20308f5c33876630a + languageName: node + linkType: hard + "glob@npm:^5.0.15": version: 5.0.15 resolution: "glob@npm:5.0.15" @@ -23844,7 +23856,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.0.0": +"minimatch@npm:^10.0.0, minimatch@npm:^10.1.1": version: 10.1.1 resolution: "minimatch@npm:10.1.1" dependencies: @@ -29929,7 +29941,7 @@ __metadata: languageName: node linkType: hard -"typedoc-plugin-markdown@npm:^4.2.3": +"typedoc-plugin-markdown@npm:^4.9.0": version: 4.9.0 resolution: "typedoc-plugin-markdown@npm:4.9.0" peerDependencies: @@ -29938,11 +29950,11 @@ __metadata: languageName: node linkType: hard -"typedoc@npm:^0.28.7": - version: 0.28.14 - resolution: "typedoc@npm:0.28.14" +"typedoc@npm:^0.28.15": + version: 0.28.15 + resolution: "typedoc@npm:0.28.15" dependencies: - "@gerrit0/mini-shiki": "npm:^3.12.0" + "@gerrit0/mini-shiki": "npm:^3.17.0" lunr: "npm:^2.3.9" markdown-it: "npm:^14.1.0" minimatch: "npm:^9.0.5" @@ -29951,7 +29963,7 @@ __metadata: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x bin: typedoc: bin/typedoc - checksum: 10c0/a8727134991ba3f9a982e9f6ceecfbcf0fac531e4865e4865cdee68ea6fe1a594228b8654011d38ffa2332b7e84e4eaa3d0dac04a8bdf36a0686d1c3f327e80b + checksum: 10c0/b5988ebebb367fed44f110bbd37baee85fe95fe10c8d5a511c33d787eb1e924e66ba54cb0763d63ed2c406adbd32fcb87bcbc3fd61b0bc8ab6f3a6c06f2de978 languageName: node linkType: hard @@ -31998,7 +32010,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.2.2, yaml@npm:^2.7.0, yaml@npm:^2.8.1": +"yaml@npm:^2.2.2, yaml@npm:^2.7.0": version: 2.8.1 resolution: "yaml@npm:2.8.1" bin: @@ -32007,6 +32019,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.8.1": + version: 2.8.2 + resolution: "yaml@npm:2.8.2" + bin: + yaml: bin.mjs + checksum: 10c0/703e4dc1e34b324aa66876d63618dcacb9ed49f7e7fe9b70f1e703645be8d640f68ab84f12b86df8ac960bac37acf5513e115de7c970940617ce0343c8c9cd96 + languageName: node + linkType: hard + "yargs-parser@npm:21.1.1, yargs-parser@npm:^21.0.0, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" From 7fe4d541c09d014ba382760cc111c9f2263bbad3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:46:52 +0100 Subject: [PATCH 21/21] chore(deps): bump pino-pretty from 13.1.2 to 13.1.3 (#3710) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/libs/logger/package.json | 2 +- yarn.lock | 31 ++++++++++++++++++++----------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json index 1313a673a2..39fdccbb71 100644 --- a/packages/libs/logger/package.json +++ b/packages/libs/logger/package.json @@ -17,7 +17,7 @@ }, "dependencies": { "pino": "^10.1.0", - "pino-pretty": "^13.1.2" + "pino-pretty": "^13.1.3" }, "devDependencies": { "@eslint/js": "^9.30.1", diff --git a/yarn.lock b/yarn.lock index f61c68eb90..8d9a85b971 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4940,7 +4940,7 @@ __metadata: eslint-plugin-prettier: "npm:^5.5.1" globals: "npm:^16.3.0" pino: "npm:^10.1.0" - pino-pretty: "npm:^13.1.2" + pino-pretty: "npm:^13.1.3" prettier: "npm:^3.7.4" ts-node: "npm:^10.9.2" typescript: "npm:^5.8.3" @@ -18939,10 +18939,10 @@ __metadata: languageName: node linkType: hard -"fast-copy@npm:^3.0.2": - version: 3.0.2 - resolution: "fast-copy@npm:3.0.2" - checksum: 10c0/02e8b9fd03c8c024d2987760ce126456a0e17470850b51e11a1c3254eed6832e4733ded2d93316c82bc0b36aeb991ad1ff48d1ba95effe7add7c3ab8d8eb554a +"fast-copy@npm:^4.0.0": + version: 4.0.1 + resolution: "fast-copy@npm:4.0.1" + checksum: 10c0/5c0ccddc68cb8f071d7806681f4bb87741cc07ed3153bba49adc456607c6d38854bf921c318feba402442056f7babcdc435052f431f19b2c7c6cbeefe9ae5841 languageName: node linkType: hard @@ -25752,6 +25752,15 @@ __metadata: languageName: node linkType: hard +"pino-abstract-transport@npm:^3.0.0": + version: 3.0.0 + resolution: "pino-abstract-transport@npm:3.0.0" + dependencies: + split2: "npm:^4.0.0" + checksum: 10c0/4486e1b9508110aaf963d07741ac98d660b974dd51d8ad42077d215118e27cda20c64da46c07c926898d52540aab7c6b9c37dc0f5355c203bb1d6a72b5bd8d6c + languageName: node + linkType: hard + "pino-abstract-transport@npm:v0.5.0": version: 0.5.0 resolution: "pino-abstract-transport@npm:0.5.0" @@ -25762,26 +25771,26 @@ __metadata: languageName: node linkType: hard -"pino-pretty@npm:^13.1.2": - version: 13.1.2 - resolution: "pino-pretty@npm:13.1.2" +"pino-pretty@npm:^13.1.3": + version: 13.1.3 + resolution: "pino-pretty@npm:13.1.3" dependencies: colorette: "npm:^2.0.7" dateformat: "npm:^4.6.3" - fast-copy: "npm:^3.0.2" + fast-copy: "npm:^4.0.0" fast-safe-stringify: "npm:^2.1.1" help-me: "npm:^5.0.0" joycon: "npm:^3.1.1" minimist: "npm:^1.2.6" on-exit-leak-free: "npm:^2.1.0" - pino-abstract-transport: "npm:^2.0.0" + pino-abstract-transport: "npm:^3.0.0" pump: "npm:^3.0.0" secure-json-parse: "npm:^4.0.0" sonic-boom: "npm:^4.0.1" strip-json-comments: "npm:^5.0.2" bin: pino-pretty: bin.js - checksum: 10c0/4d8e7472e37bdb6e0d6d7d34f25f65ced46c0f64a9579bb805602321caf1c0b10359f89a1ee9742bea875f411a02ce7c19730f7a1e5387dfcfd10ff5c9804709 + checksum: 10c0/36fa382521a893290c8f6a5b2ddc28dfb87fda1d161adb6b97d80bf7d24184970d0a7eab6f8ee45c39aff4b2ec3b2e533c756899798adc270010f34ba4411063 languageName: node linkType: hard