Skip to content

Commit 8210a9b

Browse files
authored
Release 2025-07-29 (#3480)
2 parents 409ed3f + ed55849 commit 8210a9b

File tree

12 files changed

+175
-46
lines changed

12 files changed

+175
-46
lines changed

packages/apps/staking/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
VITE_APP_DASHBOARD_API_URL=http://0.0.0.0:5006
33
VITE_APP_ENVIRONMENT=testnet
44
VITE_APP_SUPPORTED_CHAINS=80002
5+
VITE_APP_WALLETCONNECT_PROJECT_ID=replace-me
56

67
# Links to header
78
VITE_HEADER_LINK_DASHBOARD=http://localhost:3004

packages/apps/staking/src/hooks/useKVStore.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ChainId, IKVStore, KVStoreClient } from '@human-protocol/sdk';
2-
import { ethers } from 'ethers';
2+
import { Eip1193Provider, ethers } from 'ethers';
33
import { useEffect, useState } from 'react';
44
import { useAccount, useWalletClient } from 'wagmi';
55
import { SUPPORTED_CHAIN_IDS } from '../constants/chains';
@@ -8,7 +8,7 @@ import { parseErrorMessage } from '../utils/string';
88
import { getKVStoreData } from '../services/dashboard';
99

1010
export const useKVStore = () => {
11-
const { address, chainId } = useAccount();
11+
const { address, chainId, connector } = useAccount();
1212
const { data: walletClient } = useWalletClient();
1313
const { showError, openSnackbar } = useSnackbar();
1414

@@ -36,9 +36,12 @@ export const useKVStore = () => {
3636
useEffect(() => {
3737
const initStakingClient = async () => {
3838
try {
39-
if (walletClient && address) {
39+
if (walletClient && address && connector) {
4040
checkSupportedChain();
41-
const provider = new ethers.BrowserProvider(window.ethereum);
41+
const eeip193Provider = await connector?.getProvider();
42+
const provider = new ethers.BrowserProvider(
43+
eeip193Provider as Eip1193Provider
44+
);
4245
const signer = await provider.getSigner();
4346

4447
const client = await KVStoreClient.build(signer);
@@ -53,7 +56,7 @@ export const useKVStore = () => {
5356

5457
initStakingClient();
5558
// eslint-disable-next-line react-hooks/exhaustive-deps
56-
}, [walletClient, address, chainId]);
59+
}, [walletClient, address, chainId, connector]);
5760

5861
const checkSupportedChain = () => {
5962
const isSupportedChain = SUPPORTED_CHAIN_IDS.includes(chainId as ChainId);

packages/apps/staking/src/hooks/useStake.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
StakerInfo,
66
StakingClient,
77
} from '@human-protocol/sdk';
8-
import { ethers } from 'ethers';
8+
import { Eip1193Provider, ethers } from 'ethers';
99
import { useEffect, useState } from 'react';
1010
import { useAccount, useWalletClient } from 'wagmi';
1111
import { useSnackbar } from '../providers/SnackProvider';
@@ -14,7 +14,7 @@ import { formatAmount } from '../utils/units';
1414
import { SUPPORTED_CHAIN_IDS } from '../constants/chains';
1515

1616
export const useStake = () => {
17-
const { address, chainId } = useAccount();
17+
const { address, chainId, connector } = useAccount();
1818
const { data: walletClient } = useWalletClient();
1919
const { showError, openSnackbar } = useSnackbar();
2020

@@ -23,13 +23,19 @@ export const useStake = () => {
2323
);
2424
const [stakingData, setStakingData] = useState<StakerInfo | null>(null);
2525
const [tokenBalance, setTokenBalance] = useState<number>(0);
26+
const [browserProvider, setBrowserProvider] =
27+
useState<ethers.BrowserProvider | null>(null);
2628

2729
useEffect(() => {
2830
const initStakingClient = async () => {
2931
try {
30-
if (walletClient && address) {
32+
if (walletClient && address && connector) {
3133
checkSupportedChain();
32-
const provider = new ethers.BrowserProvider(window.ethereum);
34+
const eeip193Provider = await connector?.getProvider();
35+
const provider = new ethers.BrowserProvider(
36+
eeip193Provider as Eip1193Provider
37+
);
38+
setBrowserProvider(provider);
3339
const signer = await provider.getSigner();
3440

3541
const client = await StakingClient.build(signer);
@@ -45,7 +51,7 @@ export const useStake = () => {
4551

4652
initStakingClient();
4753
// eslint-disable-next-line react-hooks/exhaustive-deps
48-
}, [walletClient, address, chainId]);
54+
}, [walletClient, address, chainId, connector]);
4955

5056
const checkSupportedChain = () => {
5157
const isSupportedChain = SUPPORTED_CHAIN_IDS.includes(chainId as ChainId);
@@ -99,18 +105,16 @@ export const useStake = () => {
99105
};
100106

101107
const handleStake = async (amount: string) => {
108+
if (!browserProvider) return;
109+
102110
try {
103111
checkSupportedChain();
104-
if (stakingClient && amount) {
112+
if (stakingClient && amount && address) {
105113
const weiAmount = ethers.parseUnits(amount, 'ether');
106114
await stakingClient.approveStake(weiAmount);
107115
await stakingClient.stake(weiAmount);
108116
await fetchStakingData(stakingClient);
109-
await fetchTokenBalance(
110-
new ethers.BrowserProvider(window.ethereum),
111-
address!,
112-
chainId
113-
);
117+
await fetchTokenBalance(browserProvider, address, chainId);
114118
openSnackbar('Stake successful', 'success');
115119
}
116120
} catch (error) {
@@ -120,17 +124,15 @@ export const useStake = () => {
120124
};
121125

122126
const handleUnstake = async (amount: string) => {
127+
if (!browserProvider) return;
128+
123129
try {
124130
checkSupportedChain();
125-
if (stakingClient && amount) {
131+
if (stakingClient && amount && address) {
126132
const weiAmount = ethers.parseUnits(amount, 'ether');
127133
await stakingClient.unstake(weiAmount);
128134
await fetchStakingData(stakingClient);
129-
await fetchTokenBalance(
130-
new ethers.BrowserProvider(window.ethereum),
131-
address!,
132-
chainId
133-
);
135+
await fetchTokenBalance(browserProvider, address, chainId);
134136
openSnackbar('Unstake successful', 'success');
135137
}
136138
} catch (error) {
@@ -140,16 +142,14 @@ export const useStake = () => {
140142
};
141143

142144
const handleWithdraw = async () => {
145+
if (!browserProvider) return;
146+
143147
try {
144148
checkSupportedChain();
145-
if (stakingClient) {
149+
if (stakingClient && address) {
146150
await stakingClient.withdraw();
147151
await fetchStakingData(stakingClient);
148-
await fetchTokenBalance(
149-
new ethers.BrowserProvider(window.ethereum),
150-
address!,
151-
chainId
152-
);
152+
await fetchTokenBalance(browserProvider, address, chainId);
153153
openSnackbar('Withdraw successful', 'success');
154154
}
155155
} catch (error) {

packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,13 @@ def get_escrows(
190190

191191
escrows = []
192192

193+
statuses = None
194+
if filter.status:
195+
if isinstance(filter.status, list):
196+
statuses = [s.name for s in filter.status]
197+
else:
198+
statuses = [filter.status.name]
199+
193200
escrows_data = get_data_from_subgraph(
194201
network,
195202
query=get_escrows_query(filter),
@@ -207,7 +214,7 @@ def get_escrows(
207214
filter.exchange_oracle.lower() if filter.exchange_oracle else None
208215
),
209216
"jobRequesterId": filter.job_requester_id,
210-
"status": filter.status.name if filter.status else None,
217+
"status": statuses,
211218
"from": (
212219
int(filter.date_from.timestamp()) if filter.date_from else None
213220
),

packages/sdk/python/human-protocol-sdk/human_protocol_sdk/filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(
3030
recording_oracle: Optional[str] = None,
3131
exchange_oracle: Optional[str] = None,
3232
job_requester_id: Optional[str] = None,
33-
status: Optional[Status] = None,
33+
status: Optional[Status | List[Status]] = None,
3434
date_from: Optional[datetime] = None,
3535
date_to: Optional[datetime] = None,
3636
first: int = 10,

packages/sdk/python/human-protocol-sdk/human_protocol_sdk/gql/escrow.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def get_escrows_query(filter: EscrowFilter):
3434
$recordingOracle: String
3535
$exchangeOracle: String
3636
$jobRequesterId: String
37-
$status: String
37+
$status: [String!]
3838
$from: Int
3939
$to: Int
4040
$orderDirection: String
@@ -76,7 +76,7 @@ def get_escrows_query(filter: EscrowFilter):
7676
job_requester_clause=(
7777
"jobRequesterId: $jobRequesterId" if filter.job_requester_id else ""
7878
),
79-
status_clause="status: $status" if filter.status else "",
79+
status_clause="status_in: $status" if filter.status else "",
8080
from_clause="createdAt_gte: $from" if filter.date_from else "",
8181
to_clause="createdAt_lte: $to" if filter.date_to else "",
8282
)

packages/sdk/python/human-protocol-sdk/test/human_protocol_sdk/escrow/test_escrow_utils.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def side_effect(subgraph_url, query, params):
6969
"recordingOracle": None,
7070
"exchangeOracle": None,
7171
"jobRequesterId": "1",
72-
"status": "Pending",
72+
"status": ["Pending"],
7373
"from": 1683811973,
7474
"to": 1683812007,
7575
"first": 10,
@@ -104,6 +104,83 @@ def side_effect(subgraph_url, query, params):
104104
self.assertEqual(len(filtered), 1)
105105
self.assertEqual(filtered[0].chain_id, ChainId.POLYGON_AMOY)
106106

107+
def test_get_escrows_with_status_array(self):
108+
"""Test get_escrows with an array of statuses, similar to the TypeScript test."""
109+
with patch(
110+
"human_protocol_sdk.escrow.escrow_utils.get_data_from_subgraph"
111+
) as mock_function:
112+
mock_escrow_1 = {
113+
"id": "0x1234567890123456789012345678901234567891",
114+
"address": "0x1234567890123456789012345678901234567891",
115+
"amountPaid": "1000000000000000000",
116+
"balance": "1000000000000000000",
117+
"count": "1",
118+
"factoryAddress": "0x1234567890123456789012345678901234567890",
119+
"finalResultsUrl": "https://example.com",
120+
"intermediateResultsUrl": "https://example.com",
121+
"launcher": "0x1234567890123456789012345678901234567891",
122+
"manifestHash": "0x1234567890123456789012345678901234567891",
123+
"manifestUrl": "https://example.com",
124+
"recordingOracle": "0x1234567890123456789012345678901234567891",
125+
"reputationOracle": "0x1234567890123456789012345678901234567891",
126+
"exchangeOracle": "0x1234567890123456789012345678901234567891",
127+
"status": "Pending",
128+
"token": "0x1234567890123456789012345678901234567891",
129+
"totalFundedAmount": "1000000000000000000",
130+
}
131+
mock_escrow_2 = {
132+
"id": "0x1234567890123456789012345678901234567891",
133+
"address": "0x1234567890123456789012345678901234567891",
134+
"amountPaid": "1000000000000000000",
135+
"balance": "1000000000000000000",
136+
"count": "1",
137+
"factoryAddress": "0x1234567890123456789012345678901234567890",
138+
"finalResultsUrl": "https://example.com",
139+
"intermediateResultsUrl": "https://example.com",
140+
"launcher": "0x1234567890123456789012345678901234567891",
141+
"manifestHash": "0x1234567890123456789012345678901234567891",
142+
"manifestUrl": "https://example.com",
143+
"recordingOracle": "0x1234567890123456789012345678901234567891",
144+
"reputationOracle": "0x1234567890123456789012345678901234567891",
145+
"exchangeOracle": "0x1234567890123456789012345678901234567891",
146+
"status": "Complete",
147+
"token": "0x1234567890123456789012345678901234567891",
148+
"totalFundedAmount": "1000000000000000000",
149+
}
150+
151+
def side_effect(subgraph_url, query, params):
152+
if subgraph_url == NETWORKS[ChainId.POLYGON_AMOY]:
153+
return {"data": {"escrows": [mock_escrow_1, mock_escrow_2]}}
154+
155+
mock_function.side_effect = side_effect
156+
157+
filter = EscrowFilter(
158+
chain_id=ChainId.POLYGON_AMOY,
159+
status=[Status.Pending, Status.Complete],
160+
)
161+
filtered = EscrowUtils.get_escrows(filter)
162+
163+
mock_function.assert_called_with(
164+
NETWORKS[ChainId.POLYGON_AMOY],
165+
query=get_escrows_query(filter),
166+
params={
167+
"launcher": None,
168+
"reputationOracle": None,
169+
"recordingOracle": None,
170+
"exchangeOracle": None,
171+
"jobRequesterId": None,
172+
"status": ["Pending", "Complete"],
173+
"from": None,
174+
"to": None,
175+
"first": 10,
176+
"skip": 0,
177+
"orderDirection": "desc",
178+
},
179+
)
180+
self.assertEqual(len(filtered), 2)
181+
self.assertEqual(filtered[0].address, mock_escrow_1["address"])
182+
self.assertEqual(filtered[1].address, mock_escrow_2["address"])
183+
107184
def test_get_escrow(self):
108185
with patch(
109186
"human_protocol_sdk.escrow.escrow_utils.get_data_from_subgraph"

packages/sdk/typescript/human-protocol-sdk/example/escrow.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ export const getEscrows = async () => {
1010
}
1111

1212
const escrows = await EscrowUtils.getEscrows({
13-
status: EscrowStatus.Pending,
14-
from: new Date(2023, 4, 8),
15-
to: new Date(2023, 5, 8),
13+
status: [EscrowStatus.Pending, EscrowStatus.Complete],
1614
chainId: ChainId.POLYGON_AMOY,
15+
first: 1000,
1716
});
1817

19-
console.log('Pending escrows:', escrows);
18+
console.log('Pending escrows:', escrows.length);
2019
};
2120

2221
(async () => {

packages/sdk/typescript/human-protocol-sdk/src/escrow.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,11 @@ export class EscrowUtils {
16881688
throw ErrorUnsupportedChainID;
16891689
}
16901690

1691+
let statuses;
1692+
if (filter.status !== undefined) {
1693+
statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
1694+
statuses = statuses.map((status) => EscrowStatus[status]);
1695+
}
16911696
const { escrows } = await gqlFetch<{ escrows: EscrowData[] }>(
16921697
getSubgraphUrl(networkData),
16931698
GET_ESCROWS_QUERY(filter),
@@ -1697,12 +1702,7 @@ export class EscrowUtils {
16971702
reputationOracle: filter.reputationOracle?.toLowerCase(),
16981703
recordingOracle: filter.recordingOracle?.toLowerCase(),
16991704
exchangeOracle: filter.exchangeOracle?.toLowerCase(),
1700-
status:
1701-
filter.status !== undefined
1702-
? Object.entries(EscrowStatus).find(
1703-
([, value]) => value === filter.status
1704-
)?.[0]
1705-
: undefined,
1705+
status: statuses,
17061706
from: filter.from ? getUnixTimestamp(filter.from) : undefined,
17071707
to: filter.to ? getUnixTimestamp(filter.to) : undefined,
17081708
orderDirection: orderDirection,

packages/sdk/typescript/human-protocol-sdk/src/graphql/queries/escrow.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const GET_ESCROWS_QUERY = (filter: IEscrowsFilter) => {
5353
${reputationOracle ? `reputationOracle: $reputationOracle,` : ''}
5454
${recordingOracle ? `recordingOracle: $recordingOracle,` : ''}
5555
${exchangeOracle ? `exchangeOracle: $exchangeOracle,` : ''}
56-
${status !== undefined ? `status: $status,` : ''}
56+
${status !== undefined ? `status_in: $status,` : ''}
5757
${from ? `createdAt_gte: $from,` : ''}
5858
${to ? `createdAt_lte: $to,` : ''}
5959
}
@@ -66,7 +66,7 @@ export const GET_ESCROWS_QUERY = (filter: IEscrowsFilter) => {
6666
$reputationOracle: String
6767
$recordingOracle: String
6868
$exchangeOracle: String
69-
$status: String
69+
$status: [String!]
7070
$from: Int
7171
$to: Int
7272
$orderDirection: String

0 commit comments

Comments
 (0)