@human-protocol/sdk 1.1.19 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/base.d.ts +4 -5
  2. package/dist/base.d.ts.map +1 -1
  3. package/dist/base.js +3 -3
  4. package/dist/decorators.d.ts.map +1 -1
  5. package/dist/decorators.js +4 -2
  6. package/dist/error.d.ts +0 -6
  7. package/dist/error.d.ts.map +1 -1
  8. package/dist/error.js +2 -14
  9. package/dist/escrow.d.ts +23 -24
  10. package/dist/escrow.d.ts.map +1 -1
  11. package/dist/escrow.js +86 -90
  12. package/dist/graphql/queries/{staking.d.ts → operator.d.ts} +2 -1
  13. package/dist/graphql/queries/operator.d.ts.map +1 -0
  14. package/dist/graphql/queries/{staking.js → operator.js} +24 -1
  15. package/dist/graphql/types.d.ts +5 -6
  16. package/dist/graphql/types.d.ts.map +1 -1
  17. package/dist/index.d.ts +2 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -1
  20. package/dist/interfaces.d.ts +28 -18
  21. package/dist/interfaces.d.ts.map +1 -1
  22. package/dist/kvstore.d.ts +8 -9
  23. package/dist/kvstore.d.ts.map +1 -1
  24. package/dist/kvstore.js +18 -31
  25. package/dist/operator.d.ts +68 -0
  26. package/dist/operator.d.ts.map +1 -0
  27. package/dist/operator.js +153 -0
  28. package/dist/staking.d.ts +24 -91
  29. package/dist/staking.d.ts.map +1 -1
  30. package/dist/staking.js +47 -166
  31. package/dist/statistics.d.ts.map +1 -1
  32. package/dist/statistics.js +7 -6
  33. package/dist/types.d.ts +1 -2
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/utils.d.ts +0 -7
  36. package/dist/utils.d.ts.map +1 -1
  37. package/dist/utils.js +8 -28
  38. package/package.json +4 -4
  39. package/src/base.ts +5 -6
  40. package/src/decorators.ts +3 -2
  41. package/src/error.ts +0 -12
  42. package/src/escrow.ts +101 -114
  43. package/src/graphql/queries/{staking.ts → operator.ts} +24 -0
  44. package/src/graphql/types.ts +5 -7
  45. package/src/index.ts +2 -0
  46. package/src/interfaces.ts +30 -18
  47. package/src/kvstore.ts +20 -38
  48. package/src/operator.ts +192 -0
  49. package/src/staking.ts +49 -182
  50. package/src/statistics.ts +8 -9
  51. package/src/types.ts +1 -3
  52. package/src/utils.ts +7 -29
  53. package/dist/graphql/queries/staking.d.ts.map +0 -1
package/src/interfaces.ts CHANGED
@@ -1,40 +1,52 @@
1
- import { BigNumber } from 'ethers';
2
1
  import { EscrowStatus } from './types';
3
2
  import { ChainId } from './enums';
4
3
 
5
4
  export interface IAllocation {
6
5
  escrowAddress: string;
7
6
  staker: string;
8
- tokens: BigNumber;
9
- createdAt: BigNumber;
10
- closedAt: BigNumber;
7
+ tokens: bigint;
8
+ createdAt: bigint;
9
+ closedAt: bigint;
11
10
  }
12
11
 
13
12
  export interface IReward {
14
13
  escrowAddress: string;
15
- amount: BigNumber;
14
+ amount: bigint;
16
15
  }
17
16
 
18
17
  export interface ILeader {
19
18
  id: string;
19
+ chainId: ChainId;
20
20
  address: string;
21
- amountStaked: BigNumber;
22
- amountAllocated: BigNumber;
23
- amountLocked: BigNumber;
24
- lockedUntilTimestamp: BigNumber;
25
- amountWithdrawn: BigNumber;
26
- amountSlashed: BigNumber;
27
- reputation: BigNumber;
28
- reward: BigNumber;
29
- amountJobsLaunched: BigNumber;
21
+ amountStaked: bigint;
22
+ amountAllocated: bigint;
23
+ amountLocked: bigint;
24
+ lockedUntilTimestamp: bigint;
25
+ amountWithdrawn: bigint;
26
+ amountSlashed: bigint;
27
+ reputation: bigint;
28
+ reward: bigint;
29
+ amountJobsLaunched: bigint;
30
30
  role?: string;
31
- fee?: BigNumber;
31
+ fee?: bigint;
32
32
  publicKey?: string;
33
33
  webhookUrl?: string;
34
34
  url?: string;
35
35
  }
36
36
 
37
37
  export interface ILeadersFilter {
38
+ networks: ChainId[];
39
+ role?: string;
40
+ }
41
+
42
+ export interface IReputationNetwork {
43
+ id: string;
44
+ address: string;
45
+ operators: IOperator[];
46
+ }
47
+
48
+ export interface IOperator {
49
+ address: string;
38
50
  role?: string;
39
51
  }
40
52
 
@@ -54,9 +66,9 @@ export interface IEscrowConfig {
54
66
  recordingOracle: string;
55
67
  reputationOracle: string;
56
68
  exchangeOracle: string;
57
- recordingOracleFee: BigNumber;
58
- reputationOracleFee: BigNumber;
59
- exchangeOracleFee: BigNumber;
69
+ recordingOracleFee: bigint;
70
+ reputationOracleFee: bigint;
71
+ exchangeOracleFee: bigint;
60
72
  manifestUrl: string;
61
73
  manifestHash: string;
62
74
  }
package/src/kvstore.ts CHANGED
@@ -1,10 +1,8 @@
1
- import { Provider } from '@ethersproject/abstract-provider';
2
- import { Network } from '@ethersproject/networks';
3
1
  import {
4
2
  KVStore,
5
3
  KVStore__factory,
6
4
  } from '@human-protocol/core/typechain-types';
7
- import { Overrides, Signer, ethers } from 'ethers';
5
+ import { ContractRunner, Overrides, ethers } from 'ethers';
8
6
  import { BaseEthersClient } from './base';
9
7
  import { NETWORKS } from './constants';
10
8
  import { requiresSigner } from './decorators';
@@ -16,7 +14,6 @@ import {
16
14
  ErrorKVStoreArrayLength,
17
15
  ErrorKVStoreEmptyKey,
18
16
  ErrorProviderDoesNotExist,
19
- ErrorSigner,
20
17
  ErrorUnsupportedChainID,
21
18
  } from './error';
22
19
  import { NetworkData } from './types';
@@ -27,11 +24,11 @@ import { isValidUrl } from './utils';
27
24
  *
28
25
  * This client enables to perform actions on KVStore contract and obtain information from both the contracts and subgraph.
29
26
  *
30
- * Internally, the SDK will use one network or another according to the network ID of the `signerOrProvider`.
27
+ * Internally, the SDK will use one network or another according to the network ID of the `runner`.
31
28
  * To use this client, it is recommended to initialize it using the static `build` method.
32
29
  *
33
30
  * ```ts
34
- * static async build(signerOrProvider: Signer | Provider);
31
+ * static async build(runner: ContractRunner);
35
32
  * ```
36
33
  *
37
34
  * A `Signer` or a `Provider` should be passed depending on the use case of this module:
@@ -97,47 +94,42 @@ export class KVStoreClient extends BaseEthersClient {
97
94
  /**
98
95
  * **KVStoreClient constructor**
99
96
  *
100
- * @param {Signer | Provider} signerOrProvider - The Signer or Provider object to interact with the Ethereum network
97
+ * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network
101
98
  * @param {NetworkData} network - The network information required to connect to the KVStore contract
102
99
  */
103
- constructor(signerOrProvider: Signer | Provider, networkData: NetworkData) {
104
- super(signerOrProvider, networkData);
100
+ constructor(runner: ContractRunner, networkData: NetworkData) {
101
+ super(runner, networkData);
105
102
 
106
103
  this.contract = KVStore__factory.connect(
107
104
  networkData.kvstoreAddress,
108
- signerOrProvider
105
+ runner
109
106
  );
110
107
  }
111
108
 
112
109
  /**
113
- * Creates an instance of KVStoreClient from a Signer or Provider.
110
+ * Creates an instance of KVStoreClient from a runner.
114
111
  *
115
- * @param {Signer | Provider} signerOrProvider - The Signer or Provider object to interact with the Ethereum network
112
+ * @param {ContractRunner} runner - The Runner object to interact with the Ethereum network
116
113
  *
117
114
  * @returns {Promise<KVStoreClient>} - An instance of KVStoreClient
118
115
  * @throws {ErrorProviderDoesNotExist} - Thrown if the provider does not exist for the provided Signer
119
116
  * @throws {ErrorUnsupportedChainID} - Thrown if the network's chainId is not supported
120
117
  */
121
- public static async build(signerOrProvider: Signer | Provider) {
122
- let network: Network;
123
- if (Signer.isSigner(signerOrProvider)) {
124
- if (!signerOrProvider.provider) {
125
- throw ErrorProviderDoesNotExist;
126
- }
127
-
128
- network = await signerOrProvider.provider.getNetwork();
129
- } else {
130
- network = await signerOrProvider.getNetwork();
118
+ public static async build(runner: ContractRunner) {
119
+ if (!runner.provider) {
120
+ throw ErrorProviderDoesNotExist;
131
121
  }
132
122
 
133
- const chainId: ChainId = network.chainId;
123
+ const network = await runner.provider?.getNetwork();
124
+
125
+ const chainId: ChainId = Number(network?.chainId);
134
126
  const networkData = NETWORKS[chainId];
135
127
 
136
128
  if (!networkData) {
137
129
  throw ErrorUnsupportedChainID;
138
130
  }
139
131
 
140
- return new KVStoreClient(signerOrProvider, networkData);
132
+ return new KVStoreClient(runner, networkData);
141
133
  }
142
134
 
143
135
  /**
@@ -173,7 +165,6 @@ export class KVStoreClient extends BaseEthersClient {
173
165
  value: string,
174
166
  txOptions: Overrides = {}
175
167
  ): Promise<void> {
176
- if (!Signer.isSigner(this.signerOrProvider)) throw ErrorSigner;
177
168
  if (key === '') throw ErrorKVStoreEmptyKey;
178
169
  try {
179
170
  await (await this.contract.set(key, value, txOptions)).wait();
@@ -217,7 +208,6 @@ export class KVStoreClient extends BaseEthersClient {
217
208
  values: string[],
218
209
  txOptions: Overrides = {}
219
210
  ): Promise<void> {
220
- if (!Signer.isSigner(this.signerOrProvider)) throw ErrorSigner;
221
211
  if (keys.length !== values.length) throw ErrorKVStoreArrayLength;
222
212
  if (keys.includes('')) throw ErrorKVStoreEmptyKey;
223
213
 
@@ -261,18 +251,12 @@ export class KVStoreClient extends BaseEthersClient {
261
251
  urlKey = 'url',
262
252
  txOptions: Overrides = {}
263
253
  ): Promise<void> {
264
- if (!Signer.isSigner(this.signerOrProvider)) {
265
- throw ErrorSigner;
266
- }
267
-
268
254
  if (!isValidUrl(url)) {
269
255
  throw ErrorInvalidUrl;
270
256
  }
271
257
 
272
258
  const content = await fetch(url).then((res) => res.text());
273
- const contentHash = ethers.utils.keccak256(
274
- ethers.utils.toUtf8Bytes(content)
275
- );
259
+ const contentHash = ethers.keccak256(ethers.toUtf8Bytes(content));
276
260
 
277
261
  const hashKey = urlKey + 'Hash';
278
262
 
@@ -316,7 +300,7 @@ export class KVStoreClient extends BaseEthersClient {
316
300
  */
317
301
  public async get(address: string, key: string): Promise<string> {
318
302
  if (key === '') throw ErrorKVStoreEmptyKey;
319
- if (!ethers.utils.isAddress(address)) throw ErrorInvalidAddress;
303
+ if (!ethers.isAddress(address)) throw ErrorInvalidAddress;
320
304
 
321
305
  try {
322
306
  const result = await this.contract?.get(address, key);
@@ -354,7 +338,7 @@ export class KVStoreClient extends BaseEthersClient {
354
338
  * ```
355
339
  */
356
340
  public async getURL(address: string, urlKey = 'url'): Promise<string> {
357
- if (!ethers.utils.isAddress(address)) throw ErrorInvalidAddress;
341
+ if (!ethers.isAddress(address)) throw ErrorInvalidAddress;
358
342
  const hashKey = urlKey + 'Hash';
359
343
 
360
344
  let url = '',
@@ -378,9 +362,7 @@ export class KVStoreClient extends BaseEthersClient {
378
362
  }
379
363
 
380
364
  const content = await fetch(url).then((res) => res.text());
381
- const contentHash = ethers.utils.keccak256(
382
- ethers.utils.toUtf8Bytes(content)
383
- );
365
+ const contentHash = ethers.keccak256(ethers.toUtf8Bytes(content));
384
366
 
385
367
  if (hash !== contentHash) {
386
368
  throw ErrorInvalidHash;
@@ -0,0 +1,192 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import gqlFetch from 'graphql-request';
3
+ import {
4
+ ILeader,
5
+ ILeadersFilter,
6
+ IOperator,
7
+ IReputationNetwork,
8
+ IReward,
9
+ } from './interfaces';
10
+ import { GET_REWARD_ADDED_EVENTS_QUERY } from './graphql/queries/reward';
11
+ import { RewardAddedEventData } from './graphql';
12
+ import {
13
+ GET_LEADER_QUERY,
14
+ GET_LEADERS_QUERY,
15
+ GET_REPUTATION_NETWORK_QUERY,
16
+ } from './graphql/queries/operator';
17
+ import { ethers } from 'ethers';
18
+ import {
19
+ ErrorInvalidSlasherAddressProvided,
20
+ ErrorInvalidStakerAddressProvided,
21
+ ErrorUnsupportedChainID,
22
+ } from './error';
23
+ import { throwError } from './utils';
24
+ import { ChainId } from './enums';
25
+ import { NETWORKS } from './constants';
26
+
27
+ export class OperatorUtils {
28
+ /**
29
+ * This function returns the leader data for the given address.
30
+ *
31
+ * @param {string} address Leader address.
32
+ * @returns {ILeader} Returns the leader details.
33
+ *
34
+ *
35
+ * **Code example**
36
+ *
37
+ * ```ts
38
+ * import { OperatorUtils, ChainId } from '@human-protocol/sdk';
39
+ *
40
+ * const leader = await OperatorUtils.getLeader(ChainId.POLYGON_MUMBAI, '0x62dD51230A30401C455c8398d06F85e4EaB6309f');
41
+ * ```
42
+ */
43
+ public static async getLeader(
44
+ chainId: ChainId,
45
+ address: string
46
+ ): Promise<ILeader> {
47
+ if (!ethers.isAddress(address)) {
48
+ throw ErrorInvalidStakerAddressProvided;
49
+ }
50
+ const networkData = NETWORKS[chainId];
51
+
52
+ if (!networkData) {
53
+ throw ErrorUnsupportedChainID;
54
+ }
55
+
56
+ try {
57
+ const { leader } = await gqlFetch<{
58
+ leader: ILeader;
59
+ }>(networkData.subgraphUrl, GET_LEADER_QUERY, {
60
+ address: address.toLowerCase(),
61
+ });
62
+
63
+ return leader;
64
+ } catch (e) {
65
+ return throwError(e);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * This function returns all the leader details of the protocol.
71
+ *
72
+ * @param {ILeadersFilter} filter Filter for the leaders.
73
+ * @returns {ILeader[]} Returns an array with all the leader details.
74
+ *
75
+ *
76
+ * **Code example**
77
+ *
78
+ * ```ts
79
+ * import { OperatorUtils } from '@human-protocol/sdk';
80
+ *
81
+ * const leaders = await OperatorUtils.getLeaders();
82
+ * ```
83
+ */
84
+ public static async getLeaders(
85
+ filter: ILeadersFilter = { networks: [ChainId.POLYGON_MUMBAI] }
86
+ ): Promise<ILeader[]> {
87
+ try {
88
+ let leaders_data: ILeader[] = [];
89
+ for (const chainId of filter.networks) {
90
+ const networkData = NETWORKS[chainId];
91
+
92
+ if (!networkData) {
93
+ throw ErrorUnsupportedChainID;
94
+ }
95
+ const { leaders } = await gqlFetch<{
96
+ leaders: ILeader[];
97
+ }>(networkData.subgraphUrl, GET_LEADERS_QUERY(filter), {
98
+ role: filter.role,
99
+ });
100
+ leaders_data = leaders_data.concat(leaders);
101
+ }
102
+
103
+ return leaders_data;
104
+ } catch (e) {
105
+ return throwError(e);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Retrieves the reputation network operators of the specified address.
111
+ *
112
+ * @param {string} address - Address of the reputation oracle.
113
+ * @param {string} [role] - (Optional) Role of the operator.
114
+ * @returns {Promise<IOperator[]>} - Returns an array of operator details.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * import { OperatorUtils, ChainId } from '@human-protocol/sdk';
119
+ *
120
+ * const operators = await OperatorUtils.getReputationNetworkOperators(ChainId.POLYGON_MUMBAI, '0x62dD51230A30401C455c8398d06F85e4EaB6309f');
121
+ * ```
122
+ */
123
+ public static async getReputationNetworkOperators(
124
+ chainId: ChainId,
125
+ address: string,
126
+ role?: string
127
+ ): Promise<IOperator[]> {
128
+ const networkData = NETWORKS[chainId];
129
+
130
+ if (!networkData) {
131
+ throw ErrorUnsupportedChainID;
132
+ }
133
+ try {
134
+ const { reputationNetwork } = await gqlFetch<{
135
+ reputationNetwork: IReputationNetwork;
136
+ }>(networkData.subgraphUrl, GET_REPUTATION_NETWORK_QUERY(role), {
137
+ address: address,
138
+ role: role,
139
+ });
140
+
141
+ return reputationNetwork.operators;
142
+ } catch (e) {
143
+ return throwError(e);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * This function returns information about the rewards for a given slasher address.
149
+ *
150
+ * @param {string} slasherAddress Slasher address.
151
+ * @returns {IReward[]} Returns an array of Reward objects that contain the rewards earned by the user through slashing other users.
152
+ *
153
+ *
154
+ * **Code example**
155
+ *
156
+ * ```ts
157
+ * import { OperatorUtils, ChainId } from '@human-protocol/sdk';
158
+ *
159
+ * const rewards = await OperatorUtils.getRewards(ChainId.POLYGON_MUMBAI, '0x62dD51230A30401C455c8398d06F85e4EaB6309f');
160
+ * ```
161
+ */
162
+ public static async getRewards(
163
+ chainId: ChainId,
164
+ slasherAddress: string
165
+ ): Promise<IReward[]> {
166
+ if (!ethers.isAddress(slasherAddress)) {
167
+ throw ErrorInvalidSlasherAddressProvided;
168
+ }
169
+ const networkData = NETWORKS[chainId];
170
+
171
+ if (!networkData) {
172
+ throw ErrorUnsupportedChainID;
173
+ }
174
+
175
+ try {
176
+ const { rewardAddedEvents } = await gqlFetch<{
177
+ rewardAddedEvents: RewardAddedEventData[];
178
+ }>(networkData.subgraphUrl, GET_REWARD_ADDED_EVENTS_QUERY, {
179
+ slasherAddress: slasherAddress.toLowerCase(),
180
+ });
181
+
182
+ return rewardAddedEvents.map((reward: any) => {
183
+ return {
184
+ escrowAddress: reward.escrow,
185
+ amount: reward.amount,
186
+ };
187
+ });
188
+ } catch (e) {
189
+ return throwError(e);
190
+ }
191
+ }
192
+ }