From 2a533965eb2c61f21181211f6e66c53a055bc8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= Date: Fri, 25 Jul 2025 19:26:17 +0200 Subject: [PATCH 1/4] Support multiple statuses in EscrowFilter --- .../human_protocol_sdk/escrow/escrow_utils.py | 9 +- .../human_protocol_sdk/filter.py | 2 +- .../human_protocol_sdk/gql/escrow.py | 9 +- .../escrow/test_escrow_utils.py | 83 ++++++++++++++++++- .../human-protocol-sdk/example/escrow.ts | 7 +- .../human-protocol-sdk/src/escrow.ts | 26 ++++-- .../src/graphql/queries/escrow.ts | 4 +- .../human-protocol-sdk/src/interfaces.ts | 2 +- .../human-protocol-sdk/test/escrow.test.ts | 42 ++++++++++ 9 files changed, 164 insertions(+), 20 deletions(-) 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 aafc3132bc..35e6d1ed8f 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 @@ -190,6 +190,13 @@ def get_escrows( escrows = [] + statuses = None + if filter.status: + if isinstance(filter.status, list): + statuses = [s.name for s in filter.status] + else: + statuses = [filter.status.name] + escrows_data = get_data_from_subgraph( network, query=get_escrows_query(filter), @@ -207,7 +214,7 @@ def get_escrows( filter.exchange_oracle.lower() if filter.exchange_oracle else None ), "jobRequesterId": filter.job_requester_id, - "status": filter.status.name if filter.status else None, + "status": statuses, "from": ( int(filter.date_from.timestamp()) if filter.date_from else None ), 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 fb5cc4c483..c4f2d2bee6 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 @@ -30,7 +30,7 @@ def __init__( recording_oracle: Optional[str] = None, exchange_oracle: Optional[str] = None, job_requester_id: Optional[str] = None, - status: Optional[Status] = None, + status: Optional[Status | List[Status]] = None, date_from: Optional[datetime] = None, date_to: Optional[datetime] = None, first: int = 10, diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py index b20e2ef397..07cfc23b9e 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py @@ -27,6 +27,11 @@ def get_escrows_query(filter: EscrowFilter): + use_statuses = ( + filter.statuses + if hasattr(filter, "statuses") and filter.statuses is not None + else ([filter.status] if filter.status else None) + ) return """ query GetEscrows( $launcher: String @@ -34,7 +39,7 @@ def get_escrows_query(filter: EscrowFilter): $recordingOracle: String $exchangeOracle: String $jobRequesterId: String - $status: String + $status: [String!] $from: Int $to: Int $orderDirection: String @@ -76,7 +81,7 @@ def get_escrows_query(filter: EscrowFilter): job_requester_clause=( "jobRequesterId: $jobRequesterId" if filter.job_requester_id else "" ), - status_clause="status: $status" if filter.status else "", + status_clause="status_in: $status" if use_statuses else "", from_clause="createdAt_gte: $from" if filter.date_from else "", to_clause="createdAt_lte: $to" if filter.date_to else "", ) diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py index a13681e2a0..c050db15c8 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py @@ -35,7 +35,7 @@ def test_get_escrows(self): "intermediateResultsUrl": "https://example.com", "launcher": "0x1234567890123456789012345678901234567891", "manifestHash": "0x1234567890123456789012345678901234567891", - "manifestUrl": "https://example.com", + "manifest": "https://example.com", "recordingOracle": "0x1234567890123456789012345678901234567891", "reputationOracle": "0x1234567890123456789012345678901234567891", "exchangeOracle": "0x1234567890123456789012345678901234567891", @@ -69,7 +69,7 @@ def side_effect(subgraph_url, query, params): "recordingOracle": None, "exchangeOracle": None, "jobRequesterId": "1", - "status": "Pending", + "status": ["Pending"], "from": 1683811973, "to": 1683812007, "first": 10, @@ -104,6 +104,83 @@ def side_effect(subgraph_url, query, params): self.assertEqual(len(filtered), 1) self.assertEqual(filtered[0].chain_id, ChainId.POLYGON_AMOY) + def test_get_escrows_with_status_array(self): + """Test get_escrows with an array of statuses, similar to the TypeScript test.""" + with patch( + "human_protocol_sdk.escrow.escrow_utils.get_data_from_subgraph" + ) as mock_function: + mock_escrow_1 = { + "id": "0x1234567890123456789012345678901234567891", + "address": "0x1234567890123456789012345678901234567891", + "amountPaid": "1000000000000000000", + "balance": "1000000000000000000", + "count": "1", + "factoryAddress": "0x1234567890123456789012345678901234567890", + "finalResultsUrl": "https://example.com", + "intermediateResultsUrl": "https://example.com", + "launcher": "0x1234567890123456789012345678901234567891", + "manifestHash": "0x1234567890123456789012345678901234567891", + "manifest": "https://example.com", + "recordingOracle": "0x1234567890123456789012345678901234567891", + "reputationOracle": "0x1234567890123456789012345678901234567891", + "exchangeOracle": "0x1234567890123456789012345678901234567891", + "status": "Pending", + "token": "0x1234567890123456789012345678901234567891", + "totalFundedAmount": "1000000000000000000", + } + mock_escrow_2 = { + "id": "0x1234567890123456789012345678901234567891", + "address": "0x1234567890123456789012345678901234567891", + "amountPaid": "1000000000000000000", + "balance": "1000000000000000000", + "count": "1", + "factoryAddress": "0x1234567890123456789012345678901234567890", + "finalResultsUrl": "https://example.com", + "intermediateResultsUrl": "https://example.com", + "launcher": "0x1234567890123456789012345678901234567891", + "manifestHash": "0x1234567890123456789012345678901234567891", + "manifest": "https://example.com", + "recordingOracle": "0x1234567890123456789012345678901234567891", + "reputationOracle": "0x1234567890123456789012345678901234567891", + "exchangeOracle": "0x1234567890123456789012345678901234567891", + "status": "Complete", + "token": "0x1234567890123456789012345678901234567891", + "totalFundedAmount": "1000000000000000000", + } + + def side_effect(subgraph_url, query, params): + if subgraph_url == NETWORKS[ChainId.POLYGON_AMOY]: + return {"data": {"escrows": [mock_escrow_1, mock_escrow_2]}} + + mock_function.side_effect = side_effect + + filter = EscrowFilter( + chain_id=ChainId.POLYGON_AMOY, + status=[Status.Pending, Status.Complete], + ) + filtered = EscrowUtils.get_escrows(filter) + + mock_function.assert_called_with( + NETWORKS[ChainId.POLYGON_AMOY], + query=get_escrows_query(filter), + params={ + "launcher": None, + "reputationOracle": None, + "recordingOracle": None, + "exchangeOracle": None, + "jobRequesterId": None, + "status": ["Pending", "Complete"], + "from": None, + "to": None, + "first": 10, + "skip": 0, + "orderDirection": "desc", + }, + ) + self.assertEqual(len(filtered), 2) + self.assertEqual(filtered[0].address, mock_escrow_1["address"]) + self.assertEqual(filtered[1].address, mock_escrow_2["address"]) + def test_get_escrow(self): with patch( "human_protocol_sdk.escrow.escrow_utils.get_data_from_subgraph" @@ -119,7 +196,7 @@ def test_get_escrow(self): "intermediateResultsUrl": "https://example.com", "launcher": "0x1234567890123456789012345678901234567891", "manifestHash": "0x1234567890123456789012345678901234567891", - "manifestUrl": "https://example.com", + "manifest": "https://example.com", "recordingOracle": "0x1234567890123456789012345678901234567891", "reputationOracle": "0x1234567890123456789012345678901234567891", "exchangeOracle": "0x1234567890123456789012345678901234567891", diff --git a/packages/sdk/typescript/human-protocol-sdk/example/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/example/escrow.ts index 9b691e5c0a..db5840364e 100644 --- a/packages/sdk/typescript/human-protocol-sdk/example/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/example/escrow.ts @@ -10,13 +10,12 @@ export const getEscrows = async () => { } const escrows = await EscrowUtils.getEscrows({ - status: EscrowStatus.Pending, - from: new Date(2023, 4, 8), - to: new Date(2023, 5, 8), + status: [EscrowStatus.Pending, EscrowStatus.Complete], chainId: ChainId.POLYGON_AMOY, + first: 1000, }); - console.log('Pending escrows:', escrows); + console.log('Pending escrows:', escrows.length); }; (async () => { diff --git a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts index c583fbb8bd..a4c1f32904 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts @@ -1688,6 +1688,25 @@ export class EscrowUtils { throw ErrorUnsupportedChainID; } + let statusFilter; + if (filter.status !== undefined) { + if (Array.isArray(filter.status)) { + statusFilter = filter.status + .map( + (status) => + Object.entries(EscrowStatus).find( + ([, value]) => value === status + )?.[0] + ) + .filter(Boolean); + } else { + statusFilter = [ + Object.entries(EscrowStatus).find( + ([, value]) => value === filter.status + )?.[0], + ].filter(Boolean); + } + } const { escrows } = await gqlFetch<{ escrows: EscrowData[] }>( getSubgraphUrl(networkData), GET_ESCROWS_QUERY(filter), @@ -1697,12 +1716,7 @@ export class EscrowUtils { reputationOracle: filter.reputationOracle?.toLowerCase(), recordingOracle: filter.recordingOracle?.toLowerCase(), exchangeOracle: filter.exchangeOracle?.toLowerCase(), - status: - filter.status !== undefined - ? Object.entries(EscrowStatus).find( - ([, value]) => value === filter.status - )?.[0] - : undefined, + status: statusFilter, from: filter.from ? getUnixTimestamp(filter.from) : undefined, to: filter.to ? getUnixTimestamp(filter.to) : undefined, orderDirection: orderDirection, diff --git a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/escrow.ts index 92637f37fa..844c05bb14 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/escrow.ts @@ -53,7 +53,7 @@ export const GET_ESCROWS_QUERY = (filter: IEscrowsFilter) => { ${reputationOracle ? `reputationOracle: $reputationOracle,` : ''} ${recordingOracle ? `recordingOracle: $recordingOracle,` : ''} ${exchangeOracle ? `exchangeOracle: $exchangeOracle,` : ''} - ${status !== undefined ? `status: $status,` : ''} + ${status !== undefined ? `status_in: $status,` : ''} ${from ? `createdAt_gte: $from,` : ''} ${to ? `createdAt_lte: $to,` : ''} } @@ -66,7 +66,7 @@ export const GET_ESCROWS_QUERY = (filter: IEscrowsFilter) => { $reputationOracle: String $recordingOracle: String $exchangeOracle: String - $status: String + $status: [String!] $from: Int $to: Int $orderDirection: String diff --git a/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts b/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts index dbf4662971..eb20a5b7b5 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/interfaces.ts @@ -92,7 +92,7 @@ export interface IEscrowsFilter extends IPagination { recordingOracle?: string; exchangeOracle?: string; jobRequesterId?: string; - status?: EscrowStatus; + status?: EscrowStatus | EscrowStatus[]; from?: Date; to?: Date; chainId: ChainId; diff --git a/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts b/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts index b9d69c0a01..a0ae44fad1 100644 --- a/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts +++ b/packages/sdk/typescript/human-protocol-sdk/test/escrow.test.ts @@ -2681,6 +2681,48 @@ describe('EscrowUtils', () => { ); }); + test('should successfully getEscrows for the filter with status array', async () => { + const escrows = [ + { + id: '1', + address: '0x0', + amountPaid: '3', + balance: '0', + count: '1', + jobRequesterId: '1', + factoryAddress: '0x0', + launcher: '0x0', + status: 'Pending', + token: '0x0', + totalFundedAmount: '3', + }, + { + id: '2', + address: '0x0', + amountPaid: '3', + balance: '0', + count: '1', + jobRequesterId: '1', + factoryAddress: '0x0', + launcher: '0x0', + status: 'Complete', + token: '0x0', + totalFundedAmount: '3', + }, + ]; + const gqlFetchSpy = vi + .spyOn(gqlFetch, 'default') + .mockResolvedValue({ escrows }); + + const result = await EscrowUtils.getEscrows({ + chainId: ChainId.POLYGON_AMOY, + status: [EscrowStatus.Pending, EscrowStatus.Complete], + }); + + expect(result).toEqual(escrows); + expect(gqlFetchSpy).toHaveBeenCalled(); + }); + test('should successfully getEscrows for the filter', async () => { const escrows = [ { From 9372992abd60e8ece084ab0ebfdad3deb725b5d7 Mon Sep 17 00:00:00 2001 From: portuu3 Date: Mon, 28 Jul 2025 14:54:39 +0200 Subject: [PATCH 2/4] fix in python sdk and improvment in ts sdk for escrow status filter --- .../human_protocol_sdk/gql/escrow.py | 7 +----- .../human-protocol-sdk/src/escrow.ts | 22 ++++--------------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py index 07cfc23b9e..137cfee5a9 100644 --- a/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py +++ b/packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py @@ -27,11 +27,6 @@ def get_escrows_query(filter: EscrowFilter): - use_statuses = ( - filter.statuses - if hasattr(filter, "statuses") and filter.statuses is not None - else ([filter.status] if filter.status else None) - ) return """ query GetEscrows( $launcher: String @@ -81,7 +76,7 @@ def get_escrows_query(filter: EscrowFilter): job_requester_clause=( "jobRequesterId: $jobRequesterId" if filter.job_requester_id else "" ), - status_clause="status_in: $status" if use_statuses else "", + status_clause="status_in: $status" if filter.status else "", from_clause="createdAt_gte: $from" if filter.date_from else "", to_clause="createdAt_lte: $to" if filter.date_to else "", ) diff --git a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts index a4c1f32904..911337964b 100644 --- a/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts +++ b/packages/sdk/typescript/human-protocol-sdk/src/escrow.ts @@ -1688,24 +1688,10 @@ export class EscrowUtils { throw ErrorUnsupportedChainID; } - let statusFilter; + let statuses; if (filter.status !== undefined) { - if (Array.isArray(filter.status)) { - statusFilter = filter.status - .map( - (status) => - Object.entries(EscrowStatus).find( - ([, value]) => value === status - )?.[0] - ) - .filter(Boolean); - } else { - statusFilter = [ - Object.entries(EscrowStatus).find( - ([, value]) => value === filter.status - )?.[0], - ].filter(Boolean); - } + statuses = Array.isArray(filter.status) ? filter.status : [filter.status]; + statuses = statuses.map((status) => EscrowStatus[status]); } const { escrows } = await gqlFetch<{ escrows: EscrowData[] }>( getSubgraphUrl(networkData), @@ -1716,7 +1702,7 @@ export class EscrowUtils { reputationOracle: filter.reputationOracle?.toLowerCase(), recordingOracle: filter.recordingOracle?.toLowerCase(), exchangeOracle: filter.exchangeOracle?.toLowerCase(), - status: statusFilter, + status: statuses, from: filter.from ? getUnixTimestamp(filter.from) : undefined, to: filter.to ? getUnixTimestamp(filter.to) : undefined, orderDirection: orderDirection, From f1d72f2c16c08d3fcb7d6fcefd69092b47fe8f0a Mon Sep 17 00:00:00 2001 From: portuu3 Date: Mon, 28 Jul 2025 15:50:56 +0200 Subject: [PATCH 3/4] undo manifest change --- .../test/human_protocol_sdk/escrow/test_escrow_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py index c050db15c8..a450405a06 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py @@ -35,7 +35,7 @@ def test_get_escrows(self): "intermediateResultsUrl": "https://example.com", "launcher": "0x1234567890123456789012345678901234567891", "manifestHash": "0x1234567890123456789012345678901234567891", - "manifest": "https://example.com", + "manifestUrl": "https://example.com", "recordingOracle": "0x1234567890123456789012345678901234567891", "reputationOracle": "0x1234567890123456789012345678901234567891", "exchangeOracle": "0x1234567890123456789012345678901234567891", From 87f7ee39dcd4aeb0fc48cb3205db3886a658700f Mon Sep 17 00:00:00 2001 From: portuu3 <61605646+portuu3@users.noreply.github.com> Date: Mon, 28 Jul 2025 16:19:28 +0200 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Siarhei --- .../test/human_protocol_sdk/escrow/test_escrow_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py index a450405a06..028728c773 100644 --- a/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py +++ b/packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py @@ -120,7 +120,7 @@ def test_get_escrows_with_status_array(self): "intermediateResultsUrl": "https://example.com", "launcher": "0x1234567890123456789012345678901234567891", "manifestHash": "0x1234567890123456789012345678901234567891", - "manifest": "https://example.com", + "manifestUrl": "https://example.com", "recordingOracle": "0x1234567890123456789012345678901234567891", "reputationOracle": "0x1234567890123456789012345678901234567891", "exchangeOracle": "0x1234567890123456789012345678901234567891", @@ -139,7 +139,7 @@ def test_get_escrows_with_status_array(self): "intermediateResultsUrl": "https://example.com", "launcher": "0x1234567890123456789012345678901234567891", "manifestHash": "0x1234567890123456789012345678901234567891", - "manifest": "https://example.com", + "manifestUrl": "https://example.com", "recordingOracle": "0x1234567890123456789012345678901234567891", "reputationOracle": "0x1234567890123456789012345678901234567891", "exchangeOracle": "0x1234567890123456789012345678901234567891", @@ -196,7 +196,7 @@ def test_get_escrow(self): "intermediateResultsUrl": "https://example.com", "launcher": "0x1234567890123456789012345678901234567891", "manifestHash": "0x1234567890123456789012345678901234567891", - "manifest": "https://example.com", + "manifestUrl": "https://example.com", "recordingOracle": "0x1234567890123456789012345678901234567891", "reputationOracle": "0x1234567890123456789012345678901234567891", "exchangeOracle": "0x1234567890123456789012345678901234567891",