@ardrive/turbo-sdk 1.25.0 → 1.26.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 (48) hide show
  1. package/README.md +170 -62
  2. package/bundles/web.bundle.min.js +1584 -730
  3. package/lib/cjs/common/events.js +256 -0
  4. package/lib/cjs/common/events.test.js +470 -0
  5. package/lib/cjs/common/http.js +4 -13
  6. package/lib/cjs/common/turbo.js +6 -4
  7. package/lib/cjs/common/upload.js +65 -37
  8. package/lib/cjs/node/signer.js +30 -11
  9. package/lib/cjs/node/upload.js +7 -1
  10. package/lib/cjs/utils/axiosClient.js +3 -0
  11. package/lib/cjs/utils/readableStream.js +15 -0
  12. package/lib/cjs/version.js +1 -1
  13. package/lib/cjs/web/signer.js +55 -28
  14. package/lib/esm/common/events.js +249 -0
  15. package/lib/esm/common/events.test.js +468 -0
  16. package/lib/esm/common/http.js +4 -13
  17. package/lib/esm/common/turbo.js +6 -4
  18. package/lib/esm/common/upload.js +66 -38
  19. package/lib/esm/node/signer.js +30 -11
  20. package/lib/esm/node/upload.js +7 -1
  21. package/lib/esm/utils/axiosClient.js +3 -0
  22. package/lib/esm/utils/readableStream.js +15 -0
  23. package/lib/esm/version.js +1 -1
  24. package/lib/esm/web/signer.js +55 -28
  25. package/lib/types/common/events.d.ts +56 -0
  26. package/lib/types/common/events.d.ts.map +1 -0
  27. package/lib/types/common/events.test.d.ts +2 -0
  28. package/lib/types/common/events.test.d.ts.map +1 -0
  29. package/lib/types/common/http.d.ts +1 -2
  30. package/lib/types/common/http.d.ts.map +1 -1
  31. package/lib/types/common/signer.d.ts +1 -1
  32. package/lib/types/common/signer.d.ts.map +1 -1
  33. package/lib/types/common/turbo.d.ts +4 -4
  34. package/lib/types/common/turbo.d.ts.map +1 -1
  35. package/lib/types/common/upload.d.ts +13 -5
  36. package/lib/types/common/upload.d.ts.map +1 -1
  37. package/lib/types/node/signer.d.ts +1 -1
  38. package/lib/types/node/signer.d.ts.map +1 -1
  39. package/lib/types/node/upload.d.ts.map +1 -1
  40. package/lib/types/types.d.ts +61 -7
  41. package/lib/types/types.d.ts.map +1 -1
  42. package/lib/types/utils/axiosClient.d.ts.map +1 -1
  43. package/lib/types/utils/readableStream.d.ts +0 -1
  44. package/lib/types/utils/readableStream.d.ts.map +1 -1
  45. package/lib/types/version.d.ts +1 -1
  46. package/lib/types/web/signer.d.ts +1 -1
  47. package/lib/types/web/signer.d.ts.map +1 -1
  48. package/package.json +9 -7
package/README.md CHANGED
@@ -16,11 +16,12 @@ Welcome to the `@ardrive/turbo-sdk`! This SDK provides functionality for interac
16
16
  - [NodeJS](#nodejs)
17
17
  - [Typescript](#typescript)
18
18
  - [Examples](#examples)
19
- - [Logging](#logging)
20
19
  - [APIs](#apis)
21
20
  - [TurboFactory](#turbofactory)
22
21
  - [TurboUnauthenticatedClient](#turbounauthenticatedclient)
23
22
  - [TurboAuthenticatedClient](#turboauthenticatedclient)
23
+ - [Events](#events)
24
+ - [Logging](#logging)
24
25
  - [CLI](#cli)
25
26
  - [Installation](#installation-1)
26
27
  - [Usage](#usage-1)
@@ -56,57 +57,62 @@ import open from 'open';
56
57
  import path from 'path';
57
58
 
58
59
  async function uploadWithTurbo() {
59
- // load your JWK directly to authenticate
60
- const arweave = Arweave.init({});
61
60
  const jwk = JSON.parse(fs.readFileSync('./my-jwk.json', 'utf-8'));
62
- const address = await arweave.wallets.jwkToAddress(jwk);
63
- const turbo = TurboFactory.authenticated({ privateKey: jwk });
64
-
65
- // or provide your own signer
66
- // const signer = new ArweaveSigner(jwk);
67
- // const turbo = TurboFactory.authenticated({ signer });
68
-
69
- // get the wallet balance
70
- const { winc: balance } = await turbo.getBalance();
61
+ const signer = new ArweaveSigner(jwk);
62
+ const turbo = TurboFactory.authenticated({ signer });
71
63
 
72
- // prep file for upload
73
- const filePath = path.join(__dirname, './my-image.png');
74
- const fileSize = fs.statSync(filePath).size;
75
-
76
- // get the cost of uploading the file
77
- const [{ winc: fileSizeCost }] = await turbo.getUploadCosts({
78
- bytes: [fileSize],
79
- });
80
-
81
- // check if balance greater than upload cost, and if in browser
82
- if (balance < fileSizeCost && window !== undefined) {
83
- const { url } = await turbo.createCheckoutSession({
84
- amount: fileSizeCost,
85
- owner: address,
86
- // add a promo code if you have one
87
- });
88
-
89
- // open the URL to top-up if in browser
90
- window.open(url, '_blank');
91
- } else {
92
- // otherwise, print the URL to the console
93
- console.log('Please top up your balance via the CLI before uploading', {
94
- balance,
95
- fileSizeCost,
64
+ try {
65
+ // upload some simple data - log upload progress events
66
+ const { id, owner, dataCaches, fastFinalityIndexes } = await turbo.upload({
67
+ data: 'Hello, world!',
68
+ events: {
69
+ // overall events (includes signing and upload events)
70
+ onProgress: ({ totalBytes, processedBytes, step }) => {
71
+ console.log('Overall progress:', { totalBytes, processedBytes, step });
72
+ },
73
+ onError: ({ error, step }) => {
74
+ console.log('Overall error:', { error, step });
75
+ },
76
+ },
96
77
  });
97
- }
98
78
 
99
- // upload the file
100
- try {
79
+ // upload a file - log signing and upload progress events
80
+ const filePath = path.join(__dirname, './my-image.png');
81
+ const fileSize = fs.statSync(filePath).size;
101
82
  const { id, owner, dataCaches, fastFinalityIndexes } =
102
- // Have data in memory already? Just use it!
103
- haveDataInMemory
104
- ? await turbo.upload({ data: 'The contents of my file!' })
105
- : // Or perhaps you have a larger file that you don't want in memory? Stream it!
106
- await turbo.uploadFile({
107
- fileStreamFactory: () => fs.createReadStream(filePath),
108
- fileSizeFactory: () => fileSize,
109
- });
83
+ await turbo.uploadFile({
84
+ fileStreamFactory: () => fs.createReadStream(filePath),
85
+ fileSizeFactory: () => fileSize,
86
+ events: {
87
+ // overall events (includes signing and upload events)
88
+ onProgress: ({ totalBytes, processedBytes, step }) => {
89
+ console.log('Overall progress:', { totalBytes, processedBytes, step });
90
+ },
91
+ onError: ({ error, step }) => {
92
+ console.log('Overall error:', { error, step });
93
+ },
94
+ // signing events
95
+ onSigningProgress: ({ totalBytes, processedBytes }) => {
96
+ console.log('Signing progress:', { totalBytes, processedBytes });
97
+ },
98
+ onSigningError: (error) => {
99
+ console.log('Signing error:', { error });
100
+ },
101
+ onSigningSuccess: () => {
102
+ console.log('Signing success!');
103
+ },
104
+ // upload events
105
+ onUploadProgress: ({ totalBytes, processedBytes }) => {
106
+ console.log('Upload progress:', { totalBytes, processedBytes });
107
+ },
108
+ onUploadError: (error) => {
109
+ console.log('Upload error:', { error });
110
+ },
111
+ onUploadSuccess: () => {
112
+ console.log('Upload success!');
113
+ },
114
+ },
115
+ });
110
116
  // upload complete!
111
117
  console.log('Successfully upload data item!', {
112
118
  id,
@@ -117,9 +123,6 @@ async function uploadWithTurbo() {
117
123
  } catch (error) {
118
124
  // upload failed
119
125
  console.error('Failed to upload data item!', error);
120
- } finally {
121
- const { winc: newBalance } = await turbo.getBalance();
122
- console.log('New balance:', newBalance);
123
126
  }
124
127
  }
125
128
  ```
@@ -195,14 +198,6 @@ Examples are available in the [examples] directory. To run examples:
195
198
  - `yarn example:cjs` - runs example CJS node script
196
199
  - `yarn example:esm` - runs example ESM node script
197
200
 
198
- ## Logging
199
-
200
- The SDK uses winston for logging. You can set the log level using the `setLogLevel` method.
201
-
202
- ```typescript
203
- TurboFactory.setLogLevel('debug');
204
- ```
205
-
206
201
  ## APIs
207
202
 
208
203
  ### TurboFactory
@@ -379,9 +374,9 @@ const [uploadCostForFile] = await turbo.getUploadCosts({ bytes: [1024] });
379
374
  const { winc, adjustments } = uploadCostForFile;
380
375
  ```
381
376
 
382
- #### `uploadSignedDataItem({ dataItemStreamFactory, dataItemSizeFactory, signal })`
377
+ #### `uploadSignedDataItem({ dataItemStreamFactory, dataItemSizeFactory, signal, events })`
383
378
 
384
- Uploads a signed data item. The provided `dataItemStreamFactory` should produce a NEW signed data item stream each time is it invoked. The `dataItemSizeFactory` is a function that returns the size of the file. The `signal` is an optional [AbortSignal] that can be used to cancel the upload or timeout the request.
379
+ Uploads a signed data item. The provided `dataItemStreamFactory` should produce a NEW signed data item stream each time is it invoked. The `dataItemSizeFactory` is a function that returns the size of the file. The `signal` is an optional [AbortSignal] that can be used to cancel the upload or timeout the request. The `events` parameter is an optional object that can be used to listen to upload progress, errors, and success (refer to the [Events] section for more details).
385
380
 
386
381
  ```typescript
387
382
  const filePath = path.join(__dirname, './my-signed-data-item');
@@ -390,6 +385,18 @@ const uploadResponse = await turbo.uploadSignedDataItem({
390
385
  dataItemStreamFactory: () => fs.createReadStream(filePath),
391
386
  dataItemSizeFactory: () => dataItemSize,
392
387
  signal: AbortSignal.timeout(10_000), // cancel the upload after 10 seconds
388
+ events: {
389
+ // track upload events only
390
+ onUploadProgress: ({ totalBytes, processedBytes }) => {
391
+ console.log('Upload progress:', { totalBytes, processedBytes });
392
+ },
393
+ onUploadError: (error) => {
394
+ console.log('Upload error:', { error });
395
+ },
396
+ onUploadSuccess: () => {
397
+ console.log('Upload success!');
398
+ },
399
+ },
393
400
  });
394
401
  ```
395
402
 
@@ -515,9 +522,26 @@ const { url, winc, paymentAmount, quotedPaymentAmount, adjustments } =
515
522
  window.open(url, '_blank');
516
523
  ```
517
524
 
518
- #### `uploadFile({ fileStreamFactory, fileSizeFactory, signal, dataItemOpts })`
525
+ #### `upload({ data, signal, dataItemOpts, events })`
519
526
 
520
- Signs and uploads a raw file. The provided `fileStreamFactory` should produce a NEW file data stream each time is it invoked. The `fileSizeFactory` is a function that returns the size of the file. The `signal` is an optional [AbortSignal] that can be used to cancel the upload or timeout the request. `dataItemOpts` is an optional object that can be used to configure tags, target, and anchor for the data item upload.
527
+ The easiest way to upload data to Turbo. The `signal` is an optional [AbortSignal] that can be used to cancel the upload or timeout the request. `dataItemOpts` is an optional object that can be used to configure tags, target, and anchor for the data item upload.
528
+
529
+ ```typescript
530
+ const uploadResult = await turbo.upload({
531
+ data: 'The contents of my file!',
532
+ signal: AbortSignal.timeout(10_000), // cancel the upload after 10 seconds
533
+ dataItemOpts: {
534
+ // optional
535
+ },
536
+ events: {
537
+ // optional
538
+ },
539
+ });
540
+ ```
541
+
542
+ #### `uploadFile({ fileStreamFactory, fileSizeFactory, signal, dataItemOpts, events })`
543
+
544
+ Signs and uploads a raw file. The provided `fileStreamFactory` should produce a NEW file data stream each time it is invoked. The `fileSizeFactory` is a function that returns the size of the file. The `signal` is an optional [AbortSignal] that can be used to cancel the upload or timeout the request. `dataItemOpts` is an optional object that can be used to configure tags, target, and anchor for the data item upload.
521
545
 
522
546
  ```typescript
523
547
  const filePath = path.join(__dirname, './my-unsigned-file.txt');
@@ -539,6 +563,19 @@ const uploadResult = await turbo.uploadFile({
539
563
  ],
540
564
  // no timeout or AbortSignal provided
541
565
  },
566
+ events: {
567
+ // upload events
568
+ onUploadProgress: ({ totalBytes, processedBytes }) => {
569
+ console.log('Upload progress:', { totalBytes, processedBytes });
570
+ },
571
+ onUploadError: (error) => {
572
+ console.log('Upload error:', { error });
573
+ },
574
+ onUploadSuccess: () => {
575
+ console.log('Upload success!');
576
+ },
577
+ // add any other events you want to listen to (see `Events` section for more details)
578
+ },
542
579
  });
543
580
  ```
544
581
 
@@ -708,6 +745,76 @@ const { givenApprovals, receivedApprovals } =
708
745
  });
709
746
  ```
710
747
 
748
+ ## Events
749
+
750
+ The SDK provides events for tracking the state signing and uploading data to Turbo. You can listen to these events by providing a callback function to the `events` parameter of the `upload`, `uploadFile`, and `uploadSignedDataItem` methods.
751
+
752
+ - `onProgress` - emitted when the overall progress changes (includes both upload and signing). Each event consists of the total bytes, processed bytes, and the step (upload or signing)
753
+ - `onError` - emitted when the overall upload or signing fails (includes both upload and signing)
754
+ - `onSuccess` - emitted when the overall upload or signing succeeds (includes both upload and signing) - this is the last event emitted for the upload or signing process
755
+ - `onSigningProgress` - emitted when the signing progress changes.
756
+ - `onSigningError` - emitted when the signing fails.
757
+ - `onSigningSuccess` - emitted when the signing succeeds
758
+ - `onUploadProgress` - emitted when the upload progress changes
759
+ - `onUploadError` - emitted when the upload fails
760
+ - `onUploadSuccess` - emitted when the upload succeeds
761
+
762
+ ```typescript
763
+ const uploadResult = await turbo.upload({
764
+ data: 'The contents of my file!',
765
+ signal: AbortSignal.timeout(10_000), // cancel the upload after 10 seconds
766
+ dataItemOpts: {
767
+ // optional
768
+ },
769
+ events: {
770
+ // overall events (includes signing and upload events)
771
+ onProgress: ({ totalBytes, processedBytes, step }) => {
772
+ const percentComplete = (processedBytes / totalBytes) * 100;
773
+ console.log('Overall progress:', {
774
+ totalBytes,
775
+ processedBytes,
776
+ step,
777
+ percentComplete: percentComplete.toFixed(2) + '%', // eg 50.68%
778
+ });
779
+ },
780
+ onError: (error) => {
781
+ console.log('Overall error:', { error });
782
+ },
783
+ onSuccess: () => {
784
+ console.log('Signed and upload data item!');
785
+ },
786
+ // upload events
787
+ onUploadProgress: ({ totalBytes, processedBytes }) => {
788
+ console.log('Upload progress:', { totalBytes, processedBytes });
789
+ },
790
+ onUploadError: (error) => {
791
+ console.log('Upload error:', { error });
792
+ },
793
+ onUploadSuccess: () => {
794
+ console.log('Upload success!');
795
+ },
796
+ // signing events
797
+ onSigningProgress: ({ totalBytes, processedBytes }) => {
798
+ console.log('Signing progress:', { totalBytes, processedBytes });
799
+ },
800
+ onSigningError: (error) => {
801
+ console.log('Signing error:', { error });
802
+ },
803
+ onSigningSuccess: () => {
804
+ console.log('Signing success!');
805
+ },
806
+ },
807
+ });
808
+ ```
809
+
810
+ ## Logging
811
+
812
+ The SDK uses winston for logging. You can set the log level using the `setLogLevel` method.
813
+
814
+ ```typescript
815
+ TurboFactory.setLogLevel('debug');
816
+ ```
817
+
711
818
  ## CLI
712
819
 
713
820
  <!-- markdownlint-disable MD024 -->
@@ -1033,3 +1140,4 @@ For more information on how to contribute, please see [CONTRIBUTING.md].
1033
1140
  [AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
1034
1141
  [CONTRIBUTING.md]: ./CONTRIBUTING.md
1035
1142
  [docs/native-address]: https://docs.ar.io/glossary.html#native-address
1143
+ [Events]: #events