@human-protocol/sdk 1.0.0 → 1.0.2

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.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Human Protocol Node.js SDK
2
+
3
+ Node.js SDK to launch/manage jobs on [Human Protocol](https://www.humanprotocol.org/)
4
+
5
+ ## Installation
6
+
7
+ This SDK is available on [NPM](https://www.npmjs.com/package/@human-protocol/sdk).
8
+
9
+ yarn @human-protocol/sdk
@@ -0,0 +1,86 @@
1
+ /* eslint-disable no-console */
2
+ import { Job } from '../src';
3
+ import {
4
+ DEFAULT_GAS_PAYER_PRIVKEY,
5
+ DEFAULT_HMTOKEN_ADDR,
6
+ REPUTATION_ORACLE_PRIVKEY,
7
+ WORKER1_ADDR,
8
+ WORKER2_ADDR,
9
+ } from '../test/utils/constants';
10
+ import { manifest } from '../test/utils/manifest';
11
+ import * as dotenv from 'dotenv';
12
+
13
+ dotenv.config();
14
+
15
+ const main = async () => {
16
+ // Create job object
17
+ const newJob = new Job({
18
+ gasPayer: DEFAULT_GAS_PAYER_PRIVKEY,
19
+ reputationOracle: REPUTATION_ORACLE_PRIVKEY,
20
+ manifest: manifest,
21
+ hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
22
+ logLevel: 'debug',
23
+ });
24
+
25
+ // Initialize new job object
26
+ await newJob.initialize();
27
+
28
+ // Launch the job
29
+ await newJob.launch();
30
+
31
+ // Access the existing job
32
+ const job = new Job({
33
+ gasPayer: DEFAULT_GAS_PAYER_PRIVKEY,
34
+ reputationOracle: REPUTATION_ORACLE_PRIVKEY,
35
+ manifest: manifest,
36
+ hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
37
+ factoryAddr: newJob.contractData?.factoryAddr,
38
+ escrowAddr: newJob.contractData?.escrowAddr,
39
+ storageAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
40
+ storageSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
41
+ storageEndpoint: process.env.AWS_ENDPOINT,
42
+ storageBucket: process.env.AWS_BUCKET,
43
+ storagePublicBucket: process.env.AWS_PUBLIC_BUCKET,
44
+ logLevel: 'debug',
45
+ });
46
+
47
+ // Initialize the job object
48
+ await job.initialize();
49
+
50
+ // Setup the job
51
+ await job.setup();
52
+
53
+ console.log(
54
+ `Status: ${await job.status()}, Balance: ${(
55
+ await job.balance()
56
+ )?.toString()}`
57
+ );
58
+
59
+ // Bulk payout workers
60
+ await job.bulkPayout(
61
+ [
62
+ {
63
+ address: WORKER1_ADDR,
64
+ amount: 70,
65
+ },
66
+ {
67
+ address: WORKER2_ADDR,
68
+ amount: 30,
69
+ },
70
+ ],
71
+ {
72
+ result: 'result',
73
+ }
74
+ );
75
+
76
+ // Complete the job
77
+ await job.complete();
78
+
79
+ console.log(
80
+ `Status: ${await job.status()}, Balance: ${(
81
+ await job.balance()
82
+ )?.toString()}`
83
+ );
84
+ };
85
+
86
+ main();
@@ -0,0 +1,74 @@
1
+ /* eslint-disable no-console */
2
+ import { Job } from '../src';
3
+ import {
4
+ DEFAULT_GAS_PAYER_PRIVKEY,
5
+ DEFAULT_HMTOKEN_ADDR,
6
+ REPUTATION_ORACLE_PRIVKEY,
7
+ WORKER1_ADDR,
8
+ WORKER2_ADDR,
9
+ } from '../test/utils/constants';
10
+ import { manifest } from '../test/utils/manifest';
11
+ import * as dotenv from 'dotenv';
12
+
13
+ dotenv.config();
14
+
15
+ const main = async () => {
16
+ // Create job object
17
+ const job = new Job({
18
+ gasPayer: DEFAULT_GAS_PAYER_PRIVKEY,
19
+ reputationOracle: REPUTATION_ORACLE_PRIVKEY,
20
+ manifest: manifest,
21
+ hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
22
+ storageAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
23
+ storageSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
24
+ storageEndpoint: process.env.AWS_ENDPOINT,
25
+ storageBucket: process.env.AWS_BUCKET,
26
+ storagePublicBucket: process.env.AWS_PUBLIC_BUCKET,
27
+ logLevel: 'debug',
28
+ });
29
+
30
+ // Initialize new job
31
+ await job.initialize();
32
+
33
+ // Launch the job
34
+ await job.launch();
35
+
36
+ // Setup the job
37
+ await job.setup();
38
+
39
+ console.log(
40
+ `Status: ${await job.status()}, Balance: ${(
41
+ await job.balance()
42
+ )?.toString()}`
43
+ );
44
+
45
+ // Bulk payout workers
46
+ await job.bulkPayout(
47
+ [
48
+ {
49
+ address: WORKER1_ADDR,
50
+ amount: 70,
51
+ },
52
+ {
53
+ address: WORKER2_ADDR,
54
+ amount: 30,
55
+ },
56
+ ],
57
+ {
58
+ result: 'result',
59
+ },
60
+ false,
61
+ true
62
+ );
63
+
64
+ // Complete the job
65
+ await job.complete();
66
+
67
+ console.log(
68
+ `Status: ${await job.status()}, Balance: ${(
69
+ await job.balance()
70
+ )?.toString()}`
71
+ );
72
+ };
73
+
74
+ main();
@@ -0,0 +1,72 @@
1
+ /* eslint-disable no-console */
2
+ import { Job } from '../src';
3
+ import {
4
+ DEFAULT_GAS_PAYER_PRIVKEY,
5
+ DEFAULT_HMTOKEN_ADDR,
6
+ REPUTATION_ORACLE_PRIVKEY,
7
+ WORKER1_ADDR,
8
+ WORKER2_ADDR,
9
+ } from '../test/utils/constants';
10
+ import { manifest } from '../test/utils/manifest';
11
+ import * as dotenv from 'dotenv';
12
+
13
+ dotenv.config();
14
+
15
+ const main = async () => {
16
+ // Create job object
17
+ const job = new Job({
18
+ gasPayer: DEFAULT_GAS_PAYER_PRIVKEY,
19
+ reputationOracle: REPUTATION_ORACLE_PRIVKEY,
20
+ manifest: manifest,
21
+ hmTokenAddr: DEFAULT_HMTOKEN_ADDR,
22
+ storageAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
23
+ storageSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
24
+ storageEndpoint: process.env.AWS_ENDPOINT,
25
+ storageBucket: process.env.AWS_BUCKET,
26
+ storagePublicBucket: process.env.AWS_PUBLIC_BUCKET,
27
+ logLevel: 'debug',
28
+ });
29
+
30
+ // Initialize new job
31
+ await job.initialize();
32
+
33
+ // Launch the job
34
+ await job.launch();
35
+
36
+ // Setup the job
37
+ await job.setup();
38
+
39
+ console.log(
40
+ `Status: ${await job.status()}, Balance: ${(
41
+ await job.balance()
42
+ )?.toString()}`
43
+ );
44
+
45
+ // Bulk payout workers
46
+ await job.bulkPayout(
47
+ [
48
+ {
49
+ address: WORKER1_ADDR,
50
+ amount: 70,
51
+ },
52
+ {
53
+ address: WORKER2_ADDR,
54
+ amount: 30,
55
+ },
56
+ ],
57
+ {
58
+ result: 'result',
59
+ }
60
+ );
61
+
62
+ // Complete the job
63
+ await job.complete();
64
+
65
+ console.log(
66
+ `Status: ${await job.status()}, Balance: ${(
67
+ await job.balance()
68
+ )?.toString()}`
69
+ );
70
+ };
71
+
72
+ main();
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@human-protocol/sdk",
3
3
  "description": "Human Protocol SDK",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
5
  "files": [
6
6
  "src",
7
- "dist"
7
+ "dist",
8
+ "example",
9
+ "test"
8
10
  ],
9
11
  "main": "dist/index.js",
10
12
  "types": "dist/index.d.ts",
@@ -12,7 +14,7 @@
12
14
  "clean": "rm -rf ./dist",
13
15
  "build": "npm run clean && tsc",
14
16
  "prepublish": "npm run build",
15
- "test": "./scripts/run-test.sh",
17
+ "test": "concurrently -k -s first -g --hide 0 \"yarn workspace @human-protocol/core local\" \"sleep 5 && jest --runInBand\"",
16
18
  "lint": "eslint .",
17
19
  "lint:fix": "eslint . --fix",
18
20
  "format": "prettier --write '**/*.{ts,json}'"
@@ -36,12 +38,15 @@
36
38
  ]
37
39
  },
38
40
  "dependencies": {
39
- "@human-protocol/core": "workspace:*",
41
+ "@human-protocol/core": "^1.0.11",
40
42
  "aws-sdk": "^2.1255.0",
41
43
  "crypto": "^1.0.1",
42
44
  "dotenv": "^16.0.3",
43
45
  "ethers": "^5.7.2",
44
46
  "secp256k1": "^4.0.3",
45
47
  "winston": "^3.8.2"
48
+ },
49
+ "peerDependencies": {
50
+ "@human-protocol/core": "^1.0.11"
46
51
  }
47
52
  }
package/src/error.ts CHANGED
@@ -36,3 +36,8 @@ export const ErrorHMTokenMissing = new Error('HMToken is missing');
36
36
  export const ErrorStorageAccessDataMissing = new Error(
37
37
  'Storage access data is missing'
38
38
  );
39
+
40
+ /**
41
+ * @constant {Error} - The Staking contract is missing.
42
+ */
43
+ export const ErrorStakingMissing = new Error('Staking contract is missing');
package/src/job.ts CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  getEscrow,
21
21
  getEscrowFactory,
22
22
  getHmToken,
23
+ getStaking,
23
24
  toFullDigit,
24
25
  } from './utils';
25
26
  import {
@@ -29,6 +30,7 @@ import {
29
30
  ErrorJobNotLaunched,
30
31
  ErrorManifestMissing,
31
32
  ErrorReputationOracleMissing,
33
+ ErrorStakingMissing,
32
34
  ErrorStorageAccessDataMissing,
33
35
  } from './error';
34
36
  import { createLogger } from './logger';
@@ -94,6 +96,7 @@ export class Job {
94
96
  storageEndpoint,
95
97
  storagePublicBucket,
96
98
  storageBucket,
99
+ stakingAddr,
97
100
  logLevel = 'info',
98
101
  }: JobArguments) {
99
102
  const provider = network
@@ -134,6 +137,7 @@ export class Job {
134
137
  hmTokenAddr,
135
138
  escrowAddr,
136
139
  factoryAddr,
140
+ stakingAddr,
137
141
  };
138
142
 
139
143
  this.manifestData = { manifest };
@@ -142,8 +146,8 @@ export class Job {
142
146
  accessKeyId: storageAccessKeyId || '',
143
147
  secretAccessKey: storageSecretAccessKey || '',
144
148
  endpoint: storageEndpoint,
145
- publicBucket: storagePublicBucket || DEFAULT_BUCKET,
146
- bucket: storageBucket || DEFAULT_PUBLIC_BUCKET,
149
+ publicBucket: storagePublicBucket || DEFAULT_PUBLIC_BUCKET,
150
+ bucket: storageBucket || DEFAULT_BUCKET,
147
151
  };
148
152
 
149
153
  this._logger = createLogger(logLevel);
@@ -174,9 +178,21 @@ export class Job {
174
178
  return false;
175
179
  }
176
180
 
181
+ if (!this.contractData.stakingAddr) {
182
+ this._logError(new Error('Staking contract is missing'));
183
+ return false;
184
+ }
185
+
186
+ this._logger.info('Getting staking...');
187
+ this.contractData.staking = await getStaking(
188
+ this.contractData.stakingAddr,
189
+ this.providerData?.gasPayer
190
+ );
191
+
177
192
  this._logger.info('Deploying escrow factory...');
178
193
  this.contractData.factory = await deployEscrowFactory(
179
194
  this.contractData.hmTokenAddr,
195
+ this.contractData.stakingAddr,
180
196
  this.providerData?.gasPayer
181
197
  );
182
198
  this.contractData.factoryAddr = this.contractData.factory.address;
@@ -197,6 +213,31 @@ export class Job {
197
213
  this.providerData?.gasPayer
198
214
  );
199
215
 
216
+ this._logger.info('Checking if staking is configured...');
217
+ const stakingAddr = await this.contractData.factory.staking();
218
+ if (!stakingAddr) {
219
+ this._logError(new Error('Factory is not configured with staking'));
220
+ this.contractData.factory = undefined;
221
+
222
+ return false;
223
+ }
224
+ this._logger.info('Getting staking...');
225
+ this.contractData.staking = await getStaking(
226
+ stakingAddr,
227
+ this.providerData?.gasPayer
228
+ );
229
+ this.contractData.stakingAddr = stakingAddr;
230
+
231
+ this._logger.info('Checking if reward pool is configured...');
232
+ const rewardPoolAddr = await this.contractData.staking.rewardPool();
233
+ if (!rewardPoolAddr) {
234
+ this._logError(new Error('Staking is not configured with reward pool'));
235
+ this.contractData.staking = undefined;
236
+ this.contractData.factory = undefined;
237
+
238
+ return false;
239
+ }
240
+
200
241
  this._logger.info('Checking if escrow exists in the factory...');
201
242
  const hasEscrow = await this.contractData?.factory.hasEscrow(
202
243
  this.contractData?.escrowAddr
@@ -204,6 +245,8 @@ export class Job {
204
245
 
205
246
  if (!hasEscrow) {
206
247
  this._logError(new Error('Factory does not contain the escrow'));
248
+ this.contractData.factory = undefined;
249
+
207
250
  return false;
208
251
  }
209
252
 
@@ -214,17 +257,34 @@ export class Job {
214
257
  );
215
258
  this._logger.info('Accessed the escrow successfully.');
216
259
 
217
- this.manifestData = {
218
- ...this.manifestData,
219
- manifestlink: {
220
- url: await this.contractData?.escrow.manifestUrl(),
221
- hash: await this.contractData?.escrow.manifestHash(),
222
- },
223
- };
260
+ const manifestUrl = await this.contractData?.escrow.manifestUrl();
261
+ const manifestHash = await this.contractData?.escrow.manifestHash();
224
262
 
225
- this.manifestData.manifest = (await this._download(
226
- this.manifestData.manifestlink?.url
227
- )) as Manifest;
263
+ if (
264
+ (!manifestUrl.length || !manifestHash.length) &&
265
+ !this.manifestData?.manifest
266
+ ) {
267
+ this._logError(ErrorManifestMissing);
268
+
269
+ this.contractData.factory = undefined;
270
+ this.contractData.escrow = undefined;
271
+
272
+ return false;
273
+ }
274
+
275
+ if (manifestUrl.length && manifestHash.length) {
276
+ this.manifestData = {
277
+ ...this.manifestData,
278
+ manifestlink: {
279
+ url: manifestUrl,
280
+ hash: manifestHash,
281
+ },
282
+ };
283
+
284
+ this.manifestData.manifest = (await this._download(
285
+ manifestUrl
286
+ )) as Manifest;
287
+ }
228
288
  }
229
289
 
230
290
  return true;
@@ -238,18 +298,13 @@ export class Job {
238
298
  * @returns {Promise<boolean>} - True if the escrow is launched successfully.
239
299
  */
240
300
  async launch(): Promise<boolean> {
241
- if (!this.contractData || this.contractData.escrow) {
242
- this._logError(ErrorJobAlreadyLaunched);
243
- return false;
244
- }
245
-
246
301
  if (!this.contractData || !this.contractData.factory) {
247
302
  this._logError(ErrorJobNotInitialized);
248
303
  return false;
249
304
  }
250
305
 
251
- if (!this.manifestData || !this.manifestData.manifest) {
252
- this._logError(ErrorManifestMissing);
306
+ if (!this.contractData || this.contractData.escrow) {
307
+ this._logError(ErrorJobAlreadyLaunched);
253
308
  return false;
254
309
  }
255
310
 
@@ -269,7 +324,8 @@ export class Job {
269
324
  const txResponse = await txReceipt?.wait();
270
325
 
271
326
  const event = txResponse?.events?.find(
272
- (event) => event.event === 'Launched'
327
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
328
+ (event: any) => event.event === 'Launched'
273
329
  );
274
330
 
275
331
  const escrowAddr = event?.args?.[1];
@@ -281,21 +337,6 @@ export class Job {
281
337
  this.providerData?.gasPayer
282
338
  );
283
339
 
284
- this._logger.info('Uploading manifest...');
285
- const uploadResult = await this._upload(this.manifestData.manifest);
286
- if (!uploadResult) {
287
- this._logError(new Error('Error uploading manifest'));
288
- return false;
289
- }
290
-
291
- this.manifestData.manifestlink = {
292
- url: uploadResult.key,
293
- hash: uploadResult.hash,
294
- };
295
- this._logger.info(
296
- `Uploaded manifest.\n\tKey: ${uploadResult.key}\n\tHash: ${uploadResult.hash}`
297
- );
298
-
299
340
  return (
300
341
  (await this.status()) == EscrowStatus.Launched &&
301
342
  (await this.balance())?.toNumber() === 0
@@ -316,6 +357,16 @@ export class Job {
316
357
  return false;
317
358
  }
318
359
 
360
+ if (!this.manifestData || !this.manifestData.manifest) {
361
+ this._logError(ErrorManifestMissing);
362
+ return false;
363
+ }
364
+
365
+ if (this.manifestData.manifestlink) {
366
+ this._logError(new Error('Job is already setup'));
367
+ return false;
368
+ }
369
+
319
370
  if (!this.contractData.hmToken) {
320
371
  this._logError(ErrorHMTokenMissing);
321
372
  return false;
@@ -358,6 +409,21 @@ export class Job {
358
409
  }
359
410
  this._logger.info('HMT transferred.');
360
411
 
412
+ this._logger.info('Uploading manifest...');
413
+ const uploadResult = await this._upload(this.manifestData.manifest);
414
+ if (!uploadResult) {
415
+ this._logError(new Error('Error uploading manifest'));
416
+ return false;
417
+ }
418
+
419
+ this.manifestData.manifestlink = {
420
+ url: uploadResult.key,
421
+ hash: uploadResult.hash,
422
+ };
423
+ this._logger.info(
424
+ `Uploaded manifest.\n\tKey: ${uploadResult.key}\n\tHash: ${uploadResult.hash}`
425
+ );
426
+
361
427
  this._logger.info('Setting up the escrow...');
362
428
  const contractSetup = await this._raffleExecute(
363
429
  this.contractData.escrow,
@@ -609,6 +675,120 @@ export class Job {
609
675
  return (await this.status()) === EscrowStatus.Complete;
610
676
  }
611
677
 
678
+ /**
679
+ * **Stake HMTokens**
680
+ *
681
+ * @param {number} amount - Amount to stake
682
+ * @returns {Promise<boolean>} - True if the token is staked
683
+ */
684
+ async stake(amount: number) {
685
+ if (!this.contractData?.staking) {
686
+ this._logError(ErrorStakingMissing);
687
+ return false;
688
+ }
689
+ if (!this.contractData.hmToken) {
690
+ this._logError(ErrorHMTokenMissing);
691
+ return false;
692
+ }
693
+
694
+ const approved = await this.contractData.hmToken.approve(
695
+ this.contractData.staking.address,
696
+ toFullDigit(amount)
697
+ );
698
+
699
+ if (!approved) {
700
+ this._logError(new Error('Error approving HMTokens for staking'));
701
+ return false;
702
+ }
703
+
704
+ return await this._raffleExecute(
705
+ this.contractData.staking,
706
+ 'stake',
707
+ toFullDigit(amount)
708
+ );
709
+ }
710
+
711
+ /**
712
+ * **Unstake HMTokens**
713
+ *
714
+ * @param {number} amount - Amount to unstake
715
+ * @returns {Promise<boolean>} - True if the token is unstaked
716
+ */
717
+ async unstake(amount: number) {
718
+ if (!this.contractData?.staking) {
719
+ this._logError(ErrorStakingMissing);
720
+ return false;
721
+ }
722
+
723
+ return await this._raffleExecute(
724
+ this.contractData.staking,
725
+ 'unstake',
726
+ toFullDigit(amount)
727
+ );
728
+ }
729
+
730
+ /**
731
+ * **Withdraw unstaked HMTokens**
732
+ *
733
+ * @returns {Promise<boolean>} - True if the token is withdrawn
734
+ */
735
+ async withdraw() {
736
+ if (!this.contractData?.staking) {
737
+ this._logError(ErrorStakingMissing);
738
+ return false;
739
+ }
740
+
741
+ return await this._raffleExecute(this.contractData.staking, 'withdraw');
742
+ }
743
+
744
+ /**
745
+ * **Allocate HMTokens staked to the job**
746
+ *
747
+ * @param amount - Amount to allocate
748
+ * @returns {Promise<boolean>} - True if the token is allocated
749
+ */
750
+ async allocate(amount: number) {
751
+ if (!this.contractData?.staking) {
752
+ this._logError(ErrorStakingMissing);
753
+ return false;
754
+ }
755
+
756
+ if (!this.contractData.escrowAddr) {
757
+ this._logError(ErrorJobNotLaunched);
758
+ return false;
759
+ }
760
+
761
+ return await this._raffleExecute(
762
+ this.contractData.staking,
763
+ 'allocate',
764
+ this.contractData.escrowAddr,
765
+ toFullDigit(amount)
766
+ );
767
+ }
768
+
769
+ /**
770
+ * **Unallocate HMTokens from the job**
771
+ *
772
+ * @returns {Promise<boolean>} - True if the token is unallocated.
773
+ */
774
+ async closeAllocation() {
775
+ if (!this.contractData?.staking) {
776
+ this._logError(ErrorStakingMissing);
777
+ return false;
778
+ }
779
+
780
+ if (!this.contractData.escrowAddr) {
781
+ this._logError(ErrorJobNotLaunched);
782
+ return false;
783
+ }
784
+
785
+ return await this._raffleExecute(
786
+ this.contractData.staking,
787
+ 'closeAllocation',
788
+ this.contractData.escrowAddr
789
+ );
790
+ }
791
+
612
792
  /**
613
793
  * **Get current status of the escrow**
614
794
  *
package/src/storage.ts CHANGED
@@ -76,7 +76,7 @@ export const getKeyFromURL = (url: string): string => {
76
76
  * @param {StorageAccessData} storageAccessData - Cloud storage access data
77
77
  * @param {string} key - Key of result object
78
78
  * @param {string} privateKey - Private key to decode encrypted content
79
- * @param {string} isPublic - Whether the objest is using public bucket, or private bucket
79
+ * @param {boolean} isPublic - Whether the objest is using public bucket, or private bucket
80
80
  * @returns {Promise<Result>} - Downloaded result
81
81
  */
82
82
  export const download = async (
@@ -104,14 +104,15 @@ export const download = async (
104
104
  * @param {StorageAccessData} storageAccessData - Cloud storage access data
105
105
  * @param {Result} result - Result to upload
106
106
  * @param {string} publicKey - Public key to encrypt data if necessary
107
- * @param {string} encrypt - Whether to encrypt the result, or not
108
- * @param {string} isPublic - Whether to use public bucket, or private bucket
107
+ * @param {boolean} _encrypt - Whether to encrypt the result, or not
108
+ * @param {boolean} isPublic - Whether to use public bucket, or private bucket
109
109
  * @returns {Promise<UploadResult>} - Uploaded result with key/hash
110
110
  */
111
111
  export const upload = async (
112
112
  storageAccessData: StorageAccessData,
113
113
  result: Result,
114
114
  publicKey: string,
115
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
115
116
  encrypt = true,
116
117
  isPublic = false
117
118
  ): Promise<UploadResult> => {
@@ -128,7 +129,7 @@ export const upload = async (
128
129
  Body: content,
129
130
  };
130
131
 
131
- await s3.putObject(params);
132
+ await s3.putObject(params).promise();
132
133
 
133
134
  return { key, hash };
134
135
  };