@human-protocol/sdk 5.0.0 → 5.2.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 (56) hide show
  1. package/dist/base.d.ts +1 -10
  2. package/dist/base.d.ts.map +1 -1
  3. package/dist/base.js +0 -21
  4. package/dist/constants.d.ts +0 -1
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +7 -22
  7. package/dist/encryption.js +1 -1
  8. package/dist/enums.d.ts +0 -1
  9. package/dist/enums.d.ts.map +1 -1
  10. package/dist/enums.js +0 -1
  11. package/dist/error.d.ts +8 -0
  12. package/dist/error.d.ts.map +1 -1
  13. package/dist/error.js +9 -1
  14. package/dist/escrow.d.ts +14 -17
  15. package/dist/escrow.d.ts.map +1 -1
  16. package/dist/escrow.js +34 -33
  17. package/dist/interfaces.d.ts +14 -0
  18. package/dist/interfaces.d.ts.map +1 -1
  19. package/dist/kvstore.d.ts +9 -5
  20. package/dist/kvstore.d.ts.map +1 -1
  21. package/dist/kvstore.js +15 -15
  22. package/dist/operator.d.ts +9 -5
  23. package/dist/operator.d.ts.map +1 -1
  24. package/dist/operator.js +16 -16
  25. package/dist/staking.d.ts +6 -3
  26. package/dist/staking.d.ts.map +1 -1
  27. package/dist/staking.js +13 -15
  28. package/dist/statistics.d.ts +13 -7
  29. package/dist/statistics.d.ts.map +1 -1
  30. package/dist/statistics.js +24 -22
  31. package/dist/storage.js +4 -4
  32. package/dist/transaction.d.ts +5 -3
  33. package/dist/transaction.d.ts.map +1 -1
  34. package/dist/transaction.js +8 -11
  35. package/dist/utils.d.ts +7 -0
  36. package/dist/utils.d.ts.map +1 -1
  37. package/dist/utils.js +66 -1
  38. package/dist/worker.d.ts +5 -3
  39. package/dist/worker.d.ts.map +1 -1
  40. package/dist/worker.js +8 -10
  41. package/package.json +8 -5
  42. package/src/base.ts +1 -23
  43. package/src/constants.ts +6 -24
  44. package/src/encryption.ts +1 -1
  45. package/src/enums.ts +0 -1
  46. package/src/error.ts +14 -0
  47. package/src/escrow.ts +70 -64
  48. package/src/interfaces.ts +15 -0
  49. package/src/kvstore.ts +26 -24
  50. package/src/operator.ts +54 -26
  51. package/src/staking.ts +28 -27
  52. package/src/statistics.ts +87 -47
  53. package/src/storage.ts +4 -4
  54. package/src/transaction.ts +39 -26
  55. package/src/utils.ts +81 -0
  56. package/src/worker.ts +32 -17
@@ -1,6 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
1
  import { ethers } from 'ethers';
3
- import gqlFetch from 'graphql-request';
4
2
  import { NETWORKS } from './constants';
5
3
  import { ChainId, OrderDirection } from './enums';
6
4
  import {
@@ -17,8 +15,9 @@ import {
17
15
  InternalTransaction,
18
16
  ITransaction,
19
17
  ITransactionsFilter,
18
+ SubgraphOptions,
20
19
  } from './interfaces';
21
- import { getSubgraphUrl, getUnixTimestamp } from './utils';
20
+ import { getSubgraphUrl, getUnixTimestamp, customGqlFetch } from './utils';
22
21
 
23
22
  export class TransactionUtils {
24
23
  /**
@@ -54,6 +53,7 @@ export class TransactionUtils {
54
53
  *
55
54
  * @param {ChainId} chainId The chain ID.
56
55
  * @param {string} hash The transaction hash.
56
+ * @param {SubgraphOptions} options Optional configuration for subgraph requests.
57
57
  * @returns {Promise<ITransaction | null>} - Returns the transaction details or null if not found.
58
58
  *
59
59
  * **Code example**
@@ -66,7 +66,8 @@ export class TransactionUtils {
66
66
  */
67
67
  public static async getTransaction(
68
68
  chainId: ChainId,
69
- hash: string
69
+ hash: string,
70
+ options?: SubgraphOptions
70
71
  ): Promise<ITransaction | null> {
71
72
  if (!ethers.isHexString(hash)) {
72
73
  throw ErrorInvalidHashProvided;
@@ -77,11 +78,16 @@ export class TransactionUtils {
77
78
  throw ErrorUnsupportedChainID;
78
79
  }
79
80
 
80
- const { transaction } = await gqlFetch<{
81
+ const { transaction } = await customGqlFetch<{
81
82
  transaction: TransactionData | null;
82
- }>(getSubgraphUrl(networkData), GET_TRANSACTION_QUERY, {
83
- hash: hash.toLowerCase(),
84
- });
83
+ }>(
84
+ getSubgraphUrl(networkData),
85
+ GET_TRANSACTION_QUERY,
86
+ {
87
+ hash: hash.toLowerCase(),
88
+ },
89
+ options
90
+ );
85
91
  if (!transaction) return null;
86
92
 
87
93
  return mapTransaction(transaction);
@@ -141,6 +147,7 @@ export class TransactionUtils {
141
147
  * ```
142
148
  *
143
149
  * @param {ITransactionsFilter} filter Filter for the transactions.
150
+ * @param {SubgraphOptions} options Optional configuration for subgraph requests.
144
151
  * @returns {Promise<ITransaction[]>} Returns an array with all the transaction details.
145
152
  *
146
153
  * **Code example**
@@ -160,7 +167,8 @@ export class TransactionUtils {
160
167
  * ```
161
168
  */
162
169
  public static async getTransactions(
163
- filter: ITransactionsFilter
170
+ filter: ITransactionsFilter,
171
+ options?: SubgraphOptions
164
172
  ): Promise<ITransaction[]> {
165
173
  if (
166
174
  (!!filter.startDate || !!filter.endDate) &&
@@ -179,24 +187,29 @@ export class TransactionUtils {
179
187
  throw ErrorUnsupportedChainID;
180
188
  }
181
189
 
182
- const { transactions } = await gqlFetch<{
190
+ const { transactions } = await customGqlFetch<{
183
191
  transactions: TransactionData[];
184
- }>(getSubgraphUrl(networkData), GET_TRANSACTIONS_QUERY(filter), {
185
- fromAddress: filter?.fromAddress,
186
- toAddress: filter?.toAddress,
187
- startDate: filter?.startDate
188
- ? getUnixTimestamp(filter?.startDate)
189
- : undefined,
190
- endDate: filter.endDate ? getUnixTimestamp(filter.endDate) : undefined,
191
- startBlock: filter.startBlock ? filter.startBlock : undefined,
192
- endBlock: filter.endBlock ? filter.endBlock : undefined,
193
- method: filter.method ? filter.method : undefined,
194
- escrow: filter.escrow ? filter.escrow : undefined,
195
- token: filter.token ? filter.token : undefined,
196
- orderDirection: orderDirection,
197
- first: first,
198
- skip: skip,
199
- });
192
+ }>(
193
+ getSubgraphUrl(networkData),
194
+ GET_TRANSACTIONS_QUERY(filter),
195
+ {
196
+ fromAddress: filter?.fromAddress,
197
+ toAddress: filter?.toAddress,
198
+ startDate: filter?.startDate
199
+ ? getUnixTimestamp(filter?.startDate)
200
+ : undefined,
201
+ endDate: filter.endDate ? getUnixTimestamp(filter.endDate) : undefined,
202
+ startBlock: filter.startBlock ? filter.startBlock : undefined,
203
+ endBlock: filter.endBlock ? filter.endBlock : undefined,
204
+ method: filter.method ? filter.method : undefined,
205
+ escrow: filter.escrow ? filter.escrow : undefined,
206
+ token: filter.token ? filter.token : undefined,
207
+ orderDirection: orderDirection,
208
+ first: first,
209
+ skip: skip,
210
+ },
211
+ options
212
+ );
200
213
 
201
214
  if (!transactions) {
202
215
  return [];
package/src/utils.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { ethers } from 'ethers';
3
+ import gqlFetch from 'graphql-request';
3
4
 
4
5
  import { isURL } from 'validator';
5
6
  import { SUBGRAPH_API_KEY_PLACEHOLDER } from './constants';
6
7
  import { ChainId } from './enums';
7
8
  import {
8
9
  ContractExecutionError,
10
+ ErrorRetryParametersMissing,
11
+ ErrorRoutingRequestsToIndexerRequiresApiKey,
9
12
  EthereumError,
10
13
  InvalidArgumentError,
11
14
  NonceExpired,
@@ -15,6 +18,7 @@ import {
15
18
  WarnSubgraphApiKeyNotProvided,
16
19
  } from './error';
17
20
  import { NetworkData } from './types';
21
+ import { SubgraphOptions } from './interfaces';
18
22
 
19
23
  /**
20
24
  * **Handle and throw the error.*
@@ -99,3 +103,80 @@ export const getSubgraphUrl = (networkData: NetworkData) => {
99
103
  export const getUnixTimestamp = (date: Date): number => {
100
104
  return Math.floor(date.getTime() / 1000);
101
105
  };
106
+
107
+ export const isIndexerError = (error: any): boolean => {
108
+ if (!error) return false;
109
+
110
+ const errorMessage =
111
+ error.response?.errors?.[0]?.message ||
112
+ error.message ||
113
+ error.toString() ||
114
+ '';
115
+ return errorMessage.toLowerCase().includes('bad indexers');
116
+ };
117
+
118
+ const sleep = (ms: number): Promise<void> => {
119
+ return new Promise((resolve) => setTimeout(resolve, ms));
120
+ };
121
+
122
+ const buildIndexerUrl = (baseUrl: string, indexerId?: string): string => {
123
+ if (!indexerId) {
124
+ return baseUrl;
125
+ }
126
+ return `${baseUrl}/indexers/id/${indexerId}`;
127
+ };
128
+
129
+ /**
130
+ * Execute a GraphQL request with automatic retry logic for bad indexer errors.
131
+ * Only retries if options is provided.
132
+ */
133
+ export const customGqlFetch = async <T = any>(
134
+ url: string,
135
+ query: any,
136
+ variables?: any,
137
+ options?: SubgraphOptions
138
+ ): Promise<T> => {
139
+ const apiKey = process.env.SUBGRAPH_API_KEY;
140
+ const headers = apiKey
141
+ ? {
142
+ Authorization: `Bearer ${apiKey}`,
143
+ }
144
+ : undefined;
145
+
146
+ if (!options) {
147
+ return await gqlFetch<T>(url, query, variables, headers);
148
+ }
149
+
150
+ const hasMaxRetries = options.maxRetries !== undefined;
151
+ const hasBaseDelay = options.baseDelay !== undefined;
152
+
153
+ if (hasMaxRetries !== hasBaseDelay) {
154
+ throw ErrorRetryParametersMissing;
155
+ }
156
+ if (options.indexerId && !headers) {
157
+ throw ErrorRoutingRequestsToIndexerRequiresApiKey;
158
+ }
159
+
160
+ const targetUrl = buildIndexerUrl(url, options.indexerId);
161
+
162
+ const maxRetries = hasMaxRetries ? (options.maxRetries as number) : 0;
163
+ const baseDelay = hasBaseDelay ? (options.baseDelay as number) : 0;
164
+ let lastError: any;
165
+
166
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
167
+ try {
168
+ return await gqlFetch<T>(targetUrl, query, variables, headers);
169
+ } catch (error) {
170
+ lastError = error;
171
+
172
+ if (attempt === maxRetries || !isIndexerError(error)) {
173
+ throw error;
174
+ }
175
+
176
+ const delay = baseDelay * attempt;
177
+ await sleep(delay);
178
+ }
179
+ }
180
+
181
+ throw lastError;
182
+ };
package/src/worker.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import { ethers } from 'ethers';
2
- import gqlFetch from 'graphql-request';
3
2
  import { NETWORKS } from './constants';
4
3
  import { ChainId, OrderDirection } from './enums';
5
4
  import { ErrorInvalidAddress, ErrorUnsupportedChainID } from './error';
6
5
  import { WorkerData } from './graphql';
7
6
  import { GET_WORKER_QUERY, GET_WORKERS_QUERY } from './graphql/queries/worker';
8
- import { IWorker, IWorkersFilter } from './interfaces';
9
- import { getSubgraphUrl } from './utils';
7
+ import { IWorker, IWorkersFilter, SubgraphOptions } from './interfaces';
8
+ import { getSubgraphUrl, customGqlFetch } from './utils';
10
9
 
11
10
  export class WorkerUtils {
12
11
  /**
@@ -14,6 +13,7 @@ export class WorkerUtils {
14
13
  *
15
14
  * @param {ChainId} chainId The chain ID.
16
15
  * @param {string} address The worker address.
16
+ * @param {SubgraphOptions} options Optional configuration for subgraph requests.
17
17
  * @returns {Promise<IWorker | null>} - Returns the worker details or null if not found.
18
18
  *
19
19
  * **Code example**
@@ -26,7 +26,8 @@ export class WorkerUtils {
26
26
  */
27
27
  public static async getWorker(
28
28
  chainId: ChainId,
29
- address: string
29
+ address: string,
30
+ options?: SubgraphOptions
30
31
  ): Promise<IWorker | null> {
31
32
  const networkData = NETWORKS[chainId];
32
33
 
@@ -37,11 +38,16 @@ export class WorkerUtils {
37
38
  throw ErrorInvalidAddress;
38
39
  }
39
40
 
40
- const { worker } = await gqlFetch<{
41
+ const { worker } = await customGqlFetch<{
41
42
  worker: WorkerData | null;
42
- }>(getSubgraphUrl(networkData), GET_WORKER_QUERY, {
43
- address: address.toLowerCase(),
44
- });
43
+ }>(
44
+ getSubgraphUrl(networkData),
45
+ GET_WORKER_QUERY,
46
+ {
47
+ address: address.toLowerCase(),
48
+ },
49
+ options
50
+ );
45
51
 
46
52
  if (!worker) return null;
47
53
 
@@ -74,6 +80,7 @@ export class WorkerUtils {
74
80
  * ```
75
81
  *
76
82
  * @param {IWorkersFilter} filter Filter for the workers.
83
+ * @param {SubgraphOptions} options Optional configuration for subgraph requests.
77
84
  * @returns {Promise<IWorker[]>} Returns an array with all the worker details.
78
85
  *
79
86
  * **Code example**
@@ -89,7 +96,10 @@ export class WorkerUtils {
89
96
  * const workers = await WorkerUtils.getWorkers(filter);
90
97
  * ```
91
98
  */
92
- public static async getWorkers(filter: IWorkersFilter): Promise<IWorker[]> {
99
+ public static async getWorkers(
100
+ filter: IWorkersFilter,
101
+ options?: SubgraphOptions
102
+ ): Promise<IWorker[]> {
93
103
  const first =
94
104
  filter.first !== undefined ? Math.min(filter.first, 1000) : 10;
95
105
  const skip = filter.skip || 0;
@@ -104,15 +114,20 @@ export class WorkerUtils {
104
114
  throw ErrorInvalidAddress;
105
115
  }
106
116
 
107
- const { workers } = await gqlFetch<{
117
+ const { workers } = await customGqlFetch<{
108
118
  workers: WorkerData[];
109
- }>(getSubgraphUrl(networkData), GET_WORKERS_QUERY(filter), {
110
- address: filter?.address?.toLowerCase(),
111
- first: first,
112
- skip: skip,
113
- orderBy: orderBy,
114
- orderDirection: orderDirection,
115
- });
119
+ }>(
120
+ getSubgraphUrl(networkData),
121
+ GET_WORKERS_QUERY(filter),
122
+ {
123
+ address: filter?.address?.toLowerCase(),
124
+ first: first,
125
+ skip: skip,
126
+ orderBy: orderBy,
127
+ orderDirection: orderDirection,
128
+ },
129
+ options
130
+ );
116
131
 
117
132
  if (!workers) {
118
133
  return [];